aboutsummaryrefslogtreecommitdiff
path: root/helix-term/src/ui
diff options
context:
space:
mode:
authorath32023-12-19 01:17:12 +0000
committerGitHub2023-12-19 01:17:12 +0000
commit9ba691cd3a8ffb021cb194bd3185317a65c3194a (patch)
tree915ecd2d667ad492317e1a1748c2ba6f57983bcb /helix-term/src/ui
parent06d7dc628e5a5dac9bbfe4802c3b00754a9f7731 (diff)
Support drawing popup frame (#4313)
Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
Diffstat (limited to 'helix-term/src/ui')
-rw-r--r--helix-term/src/ui/completion.rs18
-rw-r--r--helix-term/src/ui/lsp.rs4
-rw-r--r--helix-term/src/ui/menu.rs47
-rw-r--r--helix-term/src/ui/popup.rs34
4 files changed, 81 insertions, 22 deletions
diff --git a/helix-term/src/ui/completion.rs b/helix-term/src/ui/completion.rs
index e0614722..7c6a0055 100644
--- a/helix-term/src/ui/completion.rs
+++ b/helix-term/src/ui/completion.rs
@@ -2,6 +2,7 @@ use crate::compositor::{Component, Context, Event, EventResult};
use helix_view::{
document::SavePoint,
editor::CompleteAction,
+ graphics::Margin,
theme::{Modifier, Style},
ViewId,
};
@@ -326,9 +327,18 @@ impl Completion {
}
};
});
+
+ let margin = if editor.menu_border() {
+ Margin::vertical(1)
+ } else {
+ Margin::none()
+ };
+
let popup = Popup::new(Self::ID, menu)
.with_scrollbar(false)
- .ignore_escape_key(true);
+ .ignore_escape_key(true)
+ .margin(margin);
+
let mut completion = Self {
popup,
start_offset,
@@ -569,6 +579,12 @@ impl Component for Completion {
// clear area
let background = cx.editor.theme.get("ui.popup");
surface.clear_with(doc_area, background);
+
+ if cx.editor.popup_border() {
+ use tui::widgets::{Block, Borders, Widget};
+ Widget::render(Block::default().borders(Borders::ALL), doc_area, surface);
+ }
+
markdown_doc.render(doc_area, surface, cx);
}
}
diff --git a/helix-term/src/ui/lsp.rs b/helix-term/src/ui/lsp.rs
index 880df6d8..7037b155 100644
--- a/helix-term/src/ui/lsp.rs
+++ b/helix-term/src/ui/lsp.rs
@@ -92,7 +92,9 @@ impl Component for SignatureHelp {
Some(doc) => Markdown::new(doc.clone(), Arc::clone(&self.config_loader)),
};
let sig_doc = sig_doc.parse(Some(&cx.editor.theme));
- let sig_doc_area = area.clip_top(sig_text_area.height + 2);
+ let sig_doc_area = area
+ .clip_top(sig_text_area.height + 2)
+ .clip_bottom(u16::from(cx.editor.popup_border()));
let sig_doc_para = Paragraph::new(sig_doc)
.wrap(Wrap { trim: false })
.scroll((cx.scroll.unwrap_or_default() as u16, 0));
diff --git a/helix-term/src/ui/menu.rs b/helix-term/src/ui/menu.rs
index 9704b1f2..0ee64ce9 100644
--- a/helix-term/src/ui/menu.rs
+++ b/helix-term/src/ui/menu.rs
@@ -7,11 +7,18 @@ use crate::{
use helix_core::fuzzy::MATCHER;
use nucleo::pattern::{Atom, AtomKind, CaseMatching};
use nucleo::{Config, Utf32Str};
-use tui::{buffer::Buffer as Surface, widgets::Table};
+use tui::{
+ buffer::Buffer as Surface,
+ widgets::{Block, Borders, Table, Widget},
+};
pub use tui::widgets::{Cell, Row};
-use helix_view::{editor::SmartTabConfig, graphics::Rect, Editor};
+use helix_view::{
+ editor::SmartTabConfig,
+ graphics::{Margin, Rect},
+ Editor,
+};
use tui::layout::Constraint;
pub trait Item: Sync + Send + 'static {
@@ -322,6 +329,15 @@ impl<T: Item + 'static> Component for Menu<T> {
let selected = theme.get("ui.menu.selected");
surface.clear_with(area, style);
+ let render_borders = cx.editor.menu_border();
+
+ let area = if render_borders {
+ Widget::render(Block::default().borders(Borders::ALL), area, surface);
+ area.inner(&Margin::vertical(1))
+ } else {
+ area
+ };
+
let scroll = self.scroll;
let options: Vec<_> = self
@@ -362,15 +378,19 @@ impl<T: Item + 'static> Component for Menu<T> {
false,
);
- if let Some(cursor) = self.cursor {
- let offset_from_top = cursor - scroll;
- let left = &mut surface[(area.left(), area.y + offset_from_top as u16)];
- left.set_style(selected);
- let right = &mut surface[(
- area.right().saturating_sub(1),
- area.y + offset_from_top as u16,
- )];
- right.set_style(selected);
+ let render_borders = cx.editor.menu_border();
+
+ if !render_borders {
+ if let Some(cursor) = self.cursor {
+ let offset_from_top = cursor - scroll;
+ let left = &mut surface[(area.left(), area.y + offset_from_top as u16)];
+ left.set_style(selected);
+ let right = &mut surface[(
+ area.right().saturating_sub(1),
+ area.y + offset_from_top as u16,
+ )];
+ right.set_style(selected);
+ }
}
let fits = len <= win_height;
@@ -385,12 +405,13 @@ impl<T: Item + 'static> Component for Menu<T> {
for i in 0..win_height {
cell = &mut surface[(area.right() - 1, area.top() + i as u16)];
- cell.set_symbol("▐"); // right half block
+ let half_block = if render_borders { "▌" } else { "▐" };
if scroll_line <= i && i < scroll_line + scroll_height {
// Draw scroll thumb
+ cell.set_symbol(half_block);
cell.set_fg(scroll_style.fg.unwrap_or(helix_view::theme::Color::Reset));
- } else {
+ } else if !render_borders {
// Draw scroll track
cell.set_fg(scroll_style.bg.unwrap_or(helix_view::theme::Color::Reset));
}
diff --git a/helix-term/src/ui/popup.rs b/helix-term/src/ui/popup.rs
index dff7b231..7a6ffe9d 100644
--- a/helix-term/src/ui/popup.rs
+++ b/helix-term/src/ui/popup.rs
@@ -3,7 +3,10 @@ use crate::{
compositor::{Callback, Component, Context, Event, EventResult},
ctrl, key,
};
-use tui::buffer::Buffer as Surface;
+use tui::{
+ buffer::Buffer as Surface,
+ widgets::{Block, Borders, Widget},
+};
use helix_core::Position;
use helix_view::{
@@ -252,13 +255,29 @@ impl<T: Component> Component for Popup<T> {
let background = cx.editor.theme.get("ui.popup");
surface.clear_with(area, background);
- let inner = area.inner(&self.margin);
+ let render_borders = cx.editor.popup_border();
+
+ let inner = if self
+ .contents
+ .type_name()
+ .starts_with("helix_term::ui::menu::Menu")
+ {
+ area
+ } else {
+ area.inner(&self.margin)
+ };
+
+ let border = usize::from(render_borders);
+ if render_borders {
+ Widget::render(Block::default().borders(Borders::ALL), area, surface);
+ }
+
self.contents.render(inner, surface, cx);
// render scrollbar if contents do not fit
if self.has_scrollbar {
- let win_height = inner.height as usize;
- let len = self.child_size.1 as usize;
+ let win_height = (inner.height as usize).saturating_sub(2 * border);
+ let len = (self.child_size.1 as usize).saturating_sub(2 * border);
let fits = len <= win_height;
let scroll = self.scroll;
let scroll_style = cx.editor.theme.get("ui.menu.scroll");
@@ -274,14 +293,15 @@ impl<T: Component> Component for Popup<T> {
let mut cell;
for i in 0..win_height {
- cell = &mut surface[(inner.right() - 1, inner.top() + i as u16)];
+ cell = &mut surface[(inner.right() - 1, inner.top() + (border + i) as u16)];
- cell.set_symbol("▐"); // right half block
+ let half_block = if render_borders { "▌" } else { "▐" };
if scroll_line <= i && i < scroll_line + scroll_height {
// Draw scroll thumb
+ cell.set_symbol(half_block);
cell.set_fg(scroll_style.fg.unwrap_or(helix_view::theme::Color::Reset));
- } else {
+ } else if !render_borders {
// Draw scroll track
cell.set_fg(scroll_style.bg.unwrap_or(helix_view::theme::Color::Reset));
}