diff --git a/src/terminal.go b/src/terminal.go index d77b7221..a2c7d21d 100644 --- a/src/terminal.go +++ b/src/terminal.go @@ -2739,7 +2739,9 @@ func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) { } cursor += s.contentLines sepRow := cursor - t.wborder.Top() - t.wborder.DrawHSeparator(sepRow, s.windowType) + // Separator sits above list content; hug the list below by using the + // bottom char (matters for thinblock/block where top and bottom differ). + t.wborder.DrawHSeparator(sepRow, s.windowType, true) recordSep(s.role, sepRow) cursor++ } @@ -2756,7 +2758,8 @@ func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) { t.footerWindow = win } sepRow := top - 1 - t.wborder.Top() - t.wborder.DrawHSeparator(sepRow, s.windowType) + // Separator sits below list content; hug the list above with the top char. + t.wborder.DrawHSeparator(sepRow, s.windowType, false) recordSep(s.role, sepRow) cursor = top - 2 } @@ -2937,6 +2940,16 @@ func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) { } } +// isInlineSepAboveList reports whether the recorded wborder-relative separator row sits +// above the list content window, so DrawHSeparator should use the bottom horizontal char +// to visually hug the list from above. +func (t *Terminal) isInlineSepAboveList(sepRow int) bool { + if t.wborder == nil || t.window == nil { + return false + } + return t.wborder.Top()+sepRow < t.window.Top() +} + func (t *Terminal) printInlineLabel(window tui.Window, row int, render labelPrinter, opts labelOpts, length int) { if window == nil || render == nil || window.Height() == 0 { return @@ -6123,13 +6136,13 @@ func (t *Terminal) Loop() error { case reqRedrawHeaderLabel: t.printLabel(t.headerBorder, t.headerLabel, t.headerLabelOpts, t.headerLabelLen, t.headerBorderShape, true) if t.wborder != nil && t.inlineHeaderSepRow >= 0 { - t.wborder.DrawHSeparator(t.inlineHeaderSepRow, tui.WindowHeader) + t.wborder.DrawHSeparator(t.inlineHeaderSepRow, tui.WindowHeader, t.isInlineSepAboveList(t.inlineHeaderSepRow)) t.printInlineLabel(t.wborder, t.inlineHeaderSepRow, t.headerLabel, t.headerLabelOpts, t.headerLabelLen) } case reqRedrawFooterLabel: t.printLabel(t.footerBorder, t.footerLabel, t.footerLabelOpts, t.footerLabelLen, t.footerBorderShape, true) if t.wborder != nil && t.inlineFooterSepRow >= 0 { - t.wborder.DrawHSeparator(t.inlineFooterSepRow, tui.WindowFooter) + t.wborder.DrawHSeparator(t.inlineFooterSepRow, tui.WindowFooter, t.isInlineSepAboveList(t.inlineFooterSepRow)) t.printInlineLabel(t.wborder, t.inlineFooterSepRow, t.footerLabel, t.footerLabelOpts, t.footerLabelLen) } case reqRedrawListLabel: diff --git a/src/tui/light.go b/src/tui/light.go index a1e992bf..24a79ea7 100644 --- a/src/tui/light.go +++ b/src/tui/light.go @@ -1122,7 +1122,7 @@ func (w *LightWindow) DrawHBorder() { w.drawBorder(true) } -func (w *LightWindow) DrawHSeparator(row int, windowType WindowType) { +func (w *LightWindow) DrawHSeparator(row int, windowType WindowType, useBottom bool) { if w.height == 0 { return } @@ -1147,13 +1147,17 @@ func (w *LightWindow) DrawHSeparator(row int, windowType WindowType) { // Section color for the horizontal; list-border color (w.windowType) for the T-junctions. lineColor := colorFor(windowType) junctionColor := colorFor(w.windowType) - hw := runeWidth(w.border.top) + lineChar := w.border.top + if useBottom { + lineChar = w.border.bottom + } + hw := runeWidth(lineChar) w.Move(row, 0) if !w.border.shape.HasLeft() && !w.border.shape.HasRight() { // No verticals to join, so draw a continuous horizontal across the full width. full := max(0, w.width/hw) rem := w.width - full*hw - w.CPrint(lineColor, repeat(w.border.top, full)+repeat(' ', rem)) + w.CPrint(lineColor, repeat(lineChar, full)+repeat(' ', rem)) return } lw := runeWidth(w.border.leftMid) @@ -1161,7 +1165,7 @@ func (w *LightWindow) DrawHSeparator(row int, windowType WindowType) { inner := max(0, (w.width-lw-rw)/hw) rem := (w.width - lw - rw) - inner*hw w.CPrint(junctionColor, string(w.border.leftMid)) - w.CPrint(lineColor, repeat(w.border.top, inner)+repeat(' ', rem)) + w.CPrint(lineColor, repeat(lineChar, inner)+repeat(' ', rem)) w.CPrint(junctionColor, string(w.border.rightMid)) } diff --git a/src/tui/tcell.go b/src/tui/tcell.go index 791fd952..51e79260 100644 --- a/src/tui/tcell.go +++ b/src/tui/tcell.go @@ -1017,7 +1017,7 @@ func (w *TcellWindow) DrawHBorder() { w.drawBorder(true) } -func (w *TcellWindow) DrawHSeparator(row int, windowType WindowType) { +func (w *TcellWindow) DrawHSeparator(row int, windowType WindowType, useBottom bool) { if w.height == 0 { return } @@ -1049,15 +1049,19 @@ func (w *TcellWindow) DrawHSeparator(row int, windowType WindowType) { // so the outer frame's verticals stay visually continuous. lineStyle := styleFor(windowType) junctionStyle := styleFor(w.windowType) + lineChar := w.borderStyle.top + if useBottom { + lineChar = w.borderStyle.bottom + } y := w.top + row left := w.left right := left + w.width - hw := runeWidth(w.borderStyle.top) + hw := runeWidth(lineChar) hasVert := shape.HasLeft() || shape.HasRight() if !hasVert { // No verticals to join, so draw a continuous horizontal across the full width. for x := left; x <= right-hw; x += hw { - _screen.SetContent(x, y, w.borderStyle.top, nil, lineStyle) + _screen.SetContent(x, y, lineChar, nil, lineStyle) } return } @@ -1065,7 +1069,7 @@ func (w *TcellWindow) DrawHSeparator(row int, windowType WindowType) { rightMidW := runeWidth(w.borderStyle.rightMid) max := right - leftMidW - rightMidW for x := left + leftMidW; x <= max; x += hw { - _screen.SetContent(x, y, w.borderStyle.top, nil, lineStyle) + _screen.SetContent(x, y, lineChar, nil, lineStyle) } _screen.SetContent(left, y, w.borderStyle.leftMid, nil, junctionStyle) _screen.SetContent(right-rightMidW, y, w.borderStyle.rightMid, nil, junctionStyle) diff --git a/src/tui/tui.go b/src/tui/tui.go index b6e43a4e..a3cf48df 100644 --- a/src/tui/tui.go +++ b/src/tui/tui.go @@ -830,7 +830,12 @@ type Window interface { DrawBorder() DrawHBorder() - DrawHSeparator(row int, windowType WindowType) + // DrawHSeparator draws an inline horizontal separator at `row` (relative to the + // window's top) using the color for `windowType`. When useBottom is true, the + // `bottom` horizontal char is used instead of `top` — for thinblock/block styles + // where the two characters differ, this keeps the thin line visually bonded to + // the list content that sits on the opposite side of the separator. + DrawHSeparator(row int, windowType WindowType, useBottom bool) Refresh() FinishFill()