Source File
listbox_window.go
Belonging Package
src.elv.sh/pkg/cli/tk
package tkimport// The number of lines the listing mode keeps between the current selected item// and the top and bottom edges of the window, unless the available height is// too small or if the selected item is near the top or bottom of the list.var respectDistance = 2// Determines the index of the first item to show in vertical mode.//// This function does not return the full window, but just the first item to// show, and how many initial lines to crop. The window determined by this// algorithm has the following properties://// * It always includes the selected item.//// * The combined height of all the entries in the window is equal to// min(height, combined height of all entries).//// * There are at least respectDistance rows above the first row of the selected// item, as well as that many rows below the last row of the selected item,// unless the height is too small.//// * Among all values satisfying the above conditions, the value of first is// the one closest to lastFirst.func ( ListBoxState, int) (, int) {, , := .Items, .Selected, .First:= .Len()if < 0 {= 0} else if >= {= - 1}:= .Show().CountLines()if <= {// The height is not big enough (or just big enough) to fit the selected// item. Fit as much as the selected item as we can.return , 0}// Determine the minimum amount of space required for the downward direction.:= -var intif >= 2*respectDistance {// If we can afford maintaining the respect distance on both sides, then// the minimum amount of space required is the respect distance.= respectDistance} else {// Otherwise we split the available space by half. The downward (no pun// intended) rounding here is an arbitrary choice.= / 2}// Calculate how much of the budget the downward direction can use. This is// used to 1) potentially shrink needDown 2) decide how much to expand// upward later.:= 0for := + 1; < ; ++ {+= .Show().CountLines()if >= {break}}if > {// We reached the last item without using all of needDown. That means we// don't need so much in the downward direction.=}// The maximum amount of space we can use in the upward direction is the// entire budget minus the minimum amount of space we need in the downward// direction.:= -:= 0// Extend upwards until any of the following becomes true://// * We have exhausted budgetUp;//// * We have reached item 0;//// * We have reached or passed lastFirst, satisfied the upward respect// distance, and will be able to use up the entire budget when expanding// downwards later.for := - 1; >= 0; -- {+= .Show().CountLines()if >= {return , -}if <= && >= respectDistance && + >= {return , 0}}return 0, 0}// Determines the window to show in horizontal It returns the first item// to show and the amount of height required.func ( ListBoxState, , , int) (int, int) {:= .Items:= .Len()// Lower bound of number of items that can fit in a row.:= ( + listBoxColGap) / (maxWidth(, , 0, ) + listBoxColGap)if == 0 {// We trim items that are too wide, so there is at least one item per row.= 1}if * >= {// All items can fit.return 0, ( + - 1) /}// Reduce the amount of available height by one because the last row will be// reserved for the scrollbar.--, := .Selected, .First// Start with the column containing the selected item, move left until// either the width is exhausted, or lastFirst has been reached.:= / *:= maxWidth(, , , +)for ; > ; -= {+= maxWidth(, , -, ) + listBoxColGapif > {break}}return ,}func ( Items, , , int) int {:= .Len():= 0for := ; < && < ; ++ {:= 0for , := range .Show() {+= wcwidth.Of(.Text)}if < {=}}return + 2*}
The pages are generated with Golds v0.2.8-preview. (GOOS=darwin GOARCH=arm64)