Make grid sizes dynamic

The grid used static sizes which meant that changing settings didn't
have an effect on elements of the ui, notably the sidebar width. This
patch makes the `Size` parameter of a cell a function which returns the
`int`, allowing for dynamic sizes.

A `Const` function is also included for ease of use for static sizes.
This commit is contained in:
Jeffas 2020-05-31 12:37:46 +01:00 committed by Reto Brunner
parent 3877b1aa71
commit 543510f5c1
7 changed files with 115 additions and 109 deletions

View file

@ -61,6 +61,9 @@ func SetCore(aerc *widgets.Aerc, args []string) error {
return err
}
// ensure any ui changes take effect
aerc.Invalidate()
return nil
}

View file

@ -31,10 +31,12 @@ const (
type GridSpec struct {
// One of SIZE_EXACT or SIZE_WEIGHT
Strategy int
// If Strategy = SIZE_EXACT, this is the number of cells this row/col shall
// occupy. If SIZE_WEIGHT, the space left after all exact rows/cols are
// measured is distributed amonst the remainder weighted by this value.
Size int
// If Strategy = SIZE_EXACT, this function returns the number of cells
// this row/col shall occupy. If SIZE_WEIGHT, the space left after all
// exact rows/cols are measured is distributed amonst the remainder
// weighted by the value returned by this function.
Size func() int
}
// Used to cache layout of each row/column
@ -61,11 +63,11 @@ func NewGrid() *Grid {
func MakeGrid(numRows, numCols, rowStrategy, colStrategy int) *Grid {
rows := make([]GridSpec, numRows)
for i := 0; i < numRows; i++ {
rows[i] = GridSpec{rowStrategy, 1}
rows[i] = GridSpec{rowStrategy, Const(1)}
}
cols := make([]GridSpec, numCols)
for i := 0; i < numCols; i++ {
cols[i] = GridSpec{colStrategy, 1}
cols[i] = GridSpec{colStrategy, Const(1)}
}
return NewGrid().Rows(rows).Columns(cols)
}
@ -191,10 +193,10 @@ func (grid *Grid) reflow(ctx *Context) {
nweights := 0
for _, spec := range *specs {
if spec.Strategy == SIZE_EXACT {
exact += spec.Size
exact += spec.Size()
} else if spec.Strategy == SIZE_WEIGHT {
nweights += 1
weight += spec.Size
weight += spec.Size()
}
}
offset := 0
@ -205,9 +207,9 @@ func (grid *Grid) reflow(ctx *Context) {
for _, spec := range *specs {
layout := gridLayout{Offset: offset}
if spec.Strategy == SIZE_EXACT {
layout.Size = spec.Size
layout.Size = spec.Size()
} else if spec.Strategy == SIZE_WEIGHT {
proportion := float64(spec.Size) / float64(weight)
proportion := float64(spec.Size()) / float64(weight)
size := proportion * float64(extent-exact)
if remainingExact > 0 {
extraExact := int(math.Ceil(proportion * float64(remainingExact)))
@ -284,3 +286,7 @@ func (grid *Grid) cellInvalidated(drawable Drawable) {
cell.invalid.Store(true)
grid.DoInvalidate(grid)
}
func Const(i int) func() int {
return func() int { return i }
}

View file

@ -136,18 +136,18 @@ func NewAccountWizard(conf *config.AercConfig, aerc *Aerc) *AccountWizard {
})
basics := ui.NewGrid().Rows([]ui.GridSpec{
{ui.SIZE_EXACT, 8}, // Introduction
{ui.SIZE_EXACT, 1}, // Account name (label)
{ui.SIZE_EXACT, 1}, // (input)
{ui.SIZE_EXACT, 1}, // Padding
{ui.SIZE_EXACT, 1}, // Full name (label)
{ui.SIZE_EXACT, 1}, // (input)
{ui.SIZE_EXACT, 1}, // Padding
{ui.SIZE_EXACT, 1}, // Email address (label)
{ui.SIZE_EXACT, 1}, // (input)
{ui.SIZE_WEIGHT, 1},
{ui.SIZE_EXACT, ui.Const(8)}, // Introduction
{ui.SIZE_EXACT, ui.Const(1)}, // Account name (label)
{ui.SIZE_EXACT, ui.Const(1)}, // (input)
{ui.SIZE_EXACT, ui.Const(1)}, // Padding
{ui.SIZE_EXACT, ui.Const(1)}, // Full name (label)
{ui.SIZE_EXACT, ui.Const(1)}, // (input)
{ui.SIZE_EXACT, ui.Const(1)}, // Padding
{ui.SIZE_EXACT, ui.Const(1)}, // Email address (label)
{ui.SIZE_EXACT, ui.Const(1)}, // (input)
{ui.SIZE_WEIGHT, ui.Const(1)},
}).Columns([]ui.GridSpec{
{ui.SIZE_WEIGHT, 1},
{ui.SIZE_WEIGHT, ui.Const(1)},
})
basics.AddChild(
ui.NewText("\nWelcome to aerc! Let's configure your account.\n\n" +
@ -209,23 +209,23 @@ func NewAccountWizard(conf *config.AercConfig, aerc *Aerc) *AccountWizard {
})
incoming := ui.NewGrid().Rows([]ui.GridSpec{
{ui.SIZE_EXACT, 3}, // Introduction
{ui.SIZE_EXACT, 1}, // Username (label)
{ui.SIZE_EXACT, 1}, // (input)
{ui.SIZE_EXACT, 1}, // Padding
{ui.SIZE_EXACT, 1}, // Password (label)
{ui.SIZE_EXACT, 1}, // (input)
{ui.SIZE_EXACT, 1}, // Padding
{ui.SIZE_EXACT, 1}, // Server (label)
{ui.SIZE_EXACT, 1}, // (input)
{ui.SIZE_EXACT, 1}, // Padding
{ui.SIZE_EXACT, 1}, // Connection mode (label)
{ui.SIZE_EXACT, 2}, // (input)
{ui.SIZE_EXACT, 1}, // Padding
{ui.SIZE_EXACT, 1}, // Connection string
{ui.SIZE_WEIGHT, 1},
{ui.SIZE_EXACT, ui.Const(3)}, // Introduction
{ui.SIZE_EXACT, ui.Const(1)}, // Username (label)
{ui.SIZE_EXACT, ui.Const(1)}, // (input)
{ui.SIZE_EXACT, ui.Const(1)}, // Padding
{ui.SIZE_EXACT, ui.Const(1)}, // Password (label)
{ui.SIZE_EXACT, ui.Const(1)}, // (input)
{ui.SIZE_EXACT, ui.Const(1)}, // Padding
{ui.SIZE_EXACT, ui.Const(1)}, // Server (label)
{ui.SIZE_EXACT, ui.Const(1)}, // (input)
{ui.SIZE_EXACT, ui.Const(1)}, // Padding
{ui.SIZE_EXACT, ui.Const(1)}, // Connection mode (label)
{ui.SIZE_EXACT, ui.Const(2)}, // (input)
{ui.SIZE_EXACT, ui.Const(1)}, // Padding
{ui.SIZE_EXACT, ui.Const(1)}, // Connection string
{ui.SIZE_WEIGHT, ui.Const(1)},
}).Columns([]ui.GridSpec{
{ui.SIZE_WEIGHT, 1},
{ui.SIZE_WEIGHT, ui.Const(1)},
})
incoming.AddChild(ui.NewText("\nConfigure incoming mail (IMAP)"))
incoming.AddChild(
@ -283,26 +283,26 @@ func NewAccountWizard(conf *config.AercConfig, aerc *Aerc) *AccountWizard {
})
outgoing := ui.NewGrid().Rows([]ui.GridSpec{
{ui.SIZE_EXACT, 3}, // Introduction
{ui.SIZE_EXACT, 1}, // Username (label)
{ui.SIZE_EXACT, 1}, // (input)
{ui.SIZE_EXACT, 1}, // Padding
{ui.SIZE_EXACT, 1}, // Password (label)
{ui.SIZE_EXACT, 1}, // (input)
{ui.SIZE_EXACT, 1}, // Padding
{ui.SIZE_EXACT, 1}, // Server (label)
{ui.SIZE_EXACT, 1}, // (input)
{ui.SIZE_EXACT, 1}, // Padding
{ui.SIZE_EXACT, 1}, // Connection mode (label)
{ui.SIZE_EXACT, 2}, // (input)
{ui.SIZE_EXACT, 1}, // Padding
{ui.SIZE_EXACT, 1}, // Connection string
{ui.SIZE_EXACT, 1}, // Padding
{ui.SIZE_EXACT, 1}, // Copy to sent (label)
{ui.SIZE_EXACT, 2}, // (input)
{ui.SIZE_WEIGHT, 1},
{ui.SIZE_EXACT, ui.Const(3)}, // Introduction
{ui.SIZE_EXACT, ui.Const(1)}, // Username (label)
{ui.SIZE_EXACT, ui.Const(1)}, // (input)
{ui.SIZE_EXACT, ui.Const(1)}, // Padding
{ui.SIZE_EXACT, ui.Const(1)}, // Password (label)
{ui.SIZE_EXACT, ui.Const(1)}, // (input)
{ui.SIZE_EXACT, ui.Const(1)}, // Padding
{ui.SIZE_EXACT, ui.Const(1)}, // Server (label)
{ui.SIZE_EXACT, ui.Const(1)}, // (input)
{ui.SIZE_EXACT, ui.Const(1)}, // Padding
{ui.SIZE_EXACT, ui.Const(1)}, // Connection mode (label)
{ui.SIZE_EXACT, ui.Const(2)}, // (input)
{ui.SIZE_EXACT, ui.Const(1)}, // Padding
{ui.SIZE_EXACT, ui.Const(1)}, // Connection string
{ui.SIZE_EXACT, ui.Const(1)}, // Padding
{ui.SIZE_EXACT, ui.Const(1)}, // Copy to sent (label)
{ui.SIZE_EXACT, ui.Const(2)}, // (input)
{ui.SIZE_WEIGHT, ui.Const(1)},
}).Columns([]ui.GridSpec{
{ui.SIZE_WEIGHT, 1},
{ui.SIZE_WEIGHT, ui.Const(1)},
})
outgoing.AddChild(ui.NewText("\nConfigure outgoing mail (SMTP)"))
outgoing.AddChild(
@ -374,10 +374,10 @@ func NewAccountWizard(conf *config.AercConfig, aerc *Aerc) *AccountWizard {
})
complete := ui.NewGrid().Rows([]ui.GridSpec{
{ui.SIZE_EXACT, 7}, // Introduction
{ui.SIZE_WEIGHT, 1}, // Previous / Finish / Finish & open tutorial
{ui.SIZE_EXACT, ui.Const(7)}, // Introduction
{ui.SIZE_WEIGHT, ui.Const(1)}, // Previous / Finish / Finish & open tutorial
}).Columns([]ui.GridSpec{
{ui.SIZE_WEIGHT, 1},
{ui.SIZE_WEIGHT, ui.Const(1)},
})
complete.AddChild(ui.NewText(
"\nConfiguration complete!\n\n" +

View file

@ -45,45 +45,38 @@ func NewAccountView(aerc *Aerc, conf *config.AercConfig, acct *config.AccountCon
config.UI_CONTEXT_ACCOUNT: acct.Name,
})
grid := ui.NewGrid().Rows([]ui.GridSpec{
{ui.SIZE_WEIGHT, 1},
view := &AccountView{
acct: acct,
aerc: aerc,
conf: conf,
host: host,
logger: logger,
}
view.grid = ui.NewGrid().Rows([]ui.GridSpec{
{ui.SIZE_WEIGHT, ui.Const(1)},
}).Columns([]ui.GridSpec{
{ui.SIZE_EXACT, acctUiConf.SidebarWidth},
{ui.SIZE_WEIGHT, 1},
{ui.SIZE_EXACT, func() int {
return view.UiConfig().SidebarWidth
}},
{ui.SIZE_WEIGHT, ui.Const(1)},
})
worker, err := worker.NewWorker(acct.Source, logger)
if err != nil {
host.SetStatus(fmt.Sprintf("%s: %s", acct.Name, err)).
Color(tcell.ColorDefault, tcell.ColorRed)
return &AccountView{
acct: acct,
aerc: aerc,
grid: grid,
host: host,
logger: logger,
}
return view
}
view.worker = worker
dirlist := NewDirectoryList(conf, acct, logger, worker)
view.dirlist = NewDirectoryList(conf, acct, logger, worker)
if acctUiConf.SidebarWidth > 0 {
grid.AddChild(ui.NewBordered(dirlist, ui.BORDER_RIGHT))
view.grid.AddChild(ui.NewBordered(view.dirlist, ui.BORDER_RIGHT))
}
msglist := NewMessageList(conf, logger, aerc)
grid.AddChild(msglist).At(0, 1)
view := &AccountView{
acct: acct,
aerc: aerc,
conf: conf,
dirlist: dirlist,
grid: grid,
host: host,
logger: logger,
msglist: msglist,
worker: worker,
}
view.msglist = NewMessageList(conf, logger, aerc)
view.grid.AddChild(view.msglist).At(0, 1)
go worker.Backend.Run()

View file

@ -56,11 +56,11 @@ func NewAerc(conf *config.AercConfig, logger *log.Logger,
statusbar.Push(statusline)
grid := ui.NewGrid().Rows([]ui.GridSpec{
{ui.SIZE_EXACT, 1},
{ui.SIZE_WEIGHT, 1},
{ui.SIZE_EXACT, 1},
{ui.SIZE_EXACT, ui.Const(1)},
{ui.SIZE_WEIGHT, ui.Const(1)},
{ui.SIZE_EXACT, ui.Const(1)},
}).Columns([]ui.GridSpec{
{ui.SIZE_WEIGHT, 1},
{ui.SIZE_WEIGHT, ui.Const(1)},
})
grid.AddChild(tabs.TabStrip)
grid.AddChild(tabs.TabContent).At(1, 0)
@ -552,7 +552,6 @@ func (aerc *Aerc) CloseDialog() {
return
}
func (aerc *Aerc) GetPassword(title string, prompt string) (chText chan string, chErr chan error) {
chText = make(chan string, 1)
chErr = make(chan error, 1)

View file

@ -673,13 +673,15 @@ func (c *Composer) updateGrid() {
)
if c.grid == nil {
c.grid = ui.NewGrid().Columns([]ui.GridSpec{{ui.SIZE_WEIGHT, 1}})
c.grid = ui.NewGrid().Columns([]ui.GridSpec{
{ui.SIZE_WEIGHT, ui.Const(1)},
})
}
c.grid.Rows([]ui.GridSpec{
{ui.SIZE_EXACT, height},
{ui.SIZE_EXACT, 1},
{ui.SIZE_WEIGHT, 1},
{ui.SIZE_EXACT, ui.Const(height)},
{ui.SIZE_EXACT, ui.Const(1)},
{ui.SIZE_WEIGHT, ui.Const(1)},
})
if c.header != nil {
@ -768,15 +770,18 @@ type reviewMessage struct {
}
func newReviewMessage(composer *Composer, err error) *reviewMessage {
spec := []ui.GridSpec{{ui.SIZE_EXACT, 2}, {ui.SIZE_EXACT, 1}}
spec := []ui.GridSpec{
{ui.SIZE_EXACT, ui.Const(2)},
{ui.SIZE_EXACT, ui.Const(1)},
}
for i := 0; i < len(composer.attachments)-1; i++ {
spec = append(spec, ui.GridSpec{ui.SIZE_EXACT, 1})
spec = append(spec, ui.GridSpec{ui.SIZE_EXACT, ui.Const(1)})
}
// make the last element fill remaining space
spec = append(spec, ui.GridSpec{ui.SIZE_WEIGHT, 1})
spec = append(spec, ui.GridSpec{ui.SIZE_WEIGHT, ui.Const(1)})
grid := ui.NewGrid().Rows(spec).Columns([]ui.GridSpec{
{ui.SIZE_WEIGHT, 1},
{ui.SIZE_WEIGHT, ui.Const(1)},
})
if err != nil {

View file

@ -69,7 +69,7 @@ func NewMessageViewer(acct *AccountView,
)
rows := []ui.GridSpec{
{ui.SIZE_EXACT, headerHeight},
{ui.SIZE_EXACT, ui.Const(headerHeight)},
}
if msg.PGPDetails() != nil {
@ -77,16 +77,16 @@ func NewMessageViewer(acct *AccountView,
if msg.PGPDetails().IsSigned && msg.PGPDetails().IsEncrypted {
height = 2
}
rows = append(rows, ui.GridSpec{ui.SIZE_EXACT, height})
rows = append(rows, ui.GridSpec{ui.SIZE_EXACT, ui.Const(height)})
}
rows = append(rows, []ui.GridSpec{
{ui.SIZE_EXACT, 1},
{ui.SIZE_WEIGHT, 1},
{ui.SIZE_EXACT, ui.Const(1)},
{ui.SIZE_WEIGHT, ui.Const(1)},
}...)
grid := ui.NewGrid().Rows(rows).Columns([]ui.GridSpec{
{ui.SIZE_WEIGHT, 1},
{ui.SIZE_WEIGHT, ui.Const(1)},
})
switcher := &PartSwitcher{}
@ -373,7 +373,7 @@ func (ps *PartSwitcher) MouseEvent(localX int, localY int, event tcell.Event) {
if localY < y && ps.parts[ps.selected].term != nil {
ps.parts[ps.selected].term.MouseEvent(localX, localY, event)
}
for i, _ := range ps.parts {
for i := range ps.parts {
if localY != y+i {
continue
}
@ -511,11 +511,11 @@ func NewPartViewer(acct *AccountView, conf *config.AercConfig,
}
grid := ui.NewGrid().Rows([]ui.GridSpec{
{ui.SIZE_EXACT, 3}, // Message
{ui.SIZE_EXACT, 1}, // Selector
{ui.SIZE_WEIGHT, 1},
{ui.SIZE_EXACT, ui.Const(3)}, // Message
{ui.SIZE_EXACT, ui.Const(1)}, // Selector
{ui.SIZE_WEIGHT, ui.Const(1)},
}).Columns([]ui.GridSpec{
{ui.SIZE_WEIGHT, 1},
{ui.SIZE_WEIGHT, ui.Const(1)},
})
selecter := NewSelecter([]string{"Save message", "Pipe to command"}, 0).