Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support drawing popup frame #4313

Merged
merged 2 commits into from
Dec 19, 2023
Merged

Support drawing popup frame #4313

merged 2 commits into from
Dec 19, 2023

Conversation

ath3
Copy link
Contributor

@ath3 ath3 commented Oct 16, 2022

Usability improvement: popup-frame.

On some terminals / themes the popups are hard to differentiate from the background.
This makes (for example) LSP information hard to read, and makes the daily work using ssh sessions not as good as it could be.

With this change popups and menus can be configured have a border, and is easy to tell them apart from background with every theme and terminal.

Before:
popup_before

After:
popup_after

@sudormrfbin
Copy link
Member

sudormrfbin commented Oct 16, 2022

Drawing borders for popups feel like a good default whereas having a config option for it feels a bit overkill. I suppose some might prefer a sleeker look without the border?

@the-mikedavis
Copy link
Member

I think an option for it seems ok. I prefer the borderless look but I've seen some discussions and matrix messages about wanting a border around popups

@the-mikedavis the-mikedavis added A-helix-term Area: Helix term improvements S-waiting-on-review Status: Awaiting review from a maintainer. labels Oct 16, 2022
let margin = Margin::horizontal(1);
area.height -= 1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the change here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed it now, and added .clip_bottom(1) instead.
Before the change in this function, the text would be rendered on the bottom border line for signature help.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The clip_bottom should probably be gated on the new config option as well - there's a noticeable blank line when the option is off

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the lack of bottom margin was unintentional since other popups have margins around them, and here we only miss it from the bottom.
I changed this now, so without borders if should look as it originally was.

@ath3 ath3 force-pushed the popup-frame branch 3 times, most recently from e1285fd to 00c55c5 Compare October 19, 2022 23:12
@zjp-CN
Copy link
Contributor

zjp-CN commented Oct 20, 2022

I want this to be default. I use dracula theme, and in order to distinguish the popup, I have to modify the theme:

image
image

And I haven't seen any popup in nvim without borders. The same codeactionin nvim with lspsage.nvim plugin:
image

@the-mikedavis
Copy link
Member

This change covers popups (like signature-help) but not menus (completion, code-actions). I think an option to enable/disable borders on both would be good

@ath3 ath3 force-pushed the popup-frame branch 3 times, most recently from 56ce875 to 73e707f Compare October 25, 2022 02:26
@ath3
Copy link
Contributor Author

ath3 commented Oct 25, 2022

This change covers popups (like signature-help) but not menus (completion, code-actions). I think an option to enable/disable borders on both would be good

It covers now both menus and popups, with settings to enable one of them, both, or none.

the-mikedavis
the-mikedavis previously approved these changes Oct 27, 2022
@ath3
Copy link
Contributor Author

ath3 commented Nov 17, 2022

Updated after the changes to popups having scrollbars.
Also fixed the unnecessary leading newlines in popups displayed for the selected menu item.

@ath3 ath3 force-pushed the popup-frame branch 2 times, most recently from be830c7 to 7e579ba Compare November 26, 2022 15:59
@ath3
Copy link
Contributor Author

ath3 commented Nov 26, 2022

I decided to take out the changes related to selection popup whitespace since it has nothing to do with borders.
The pr containing those changes is #4902

@ath3
Copy link
Contributor Author

ath3 commented Jan 16, 2023

I think this pr is ready for merge.
The last force-push was only to fix a merge conflict with newer changes on master.


if render_borders {
Widget::render(Block::default().borders(Borders::ALL), area, surface);
area = area.clip_top(1).clip_bottom(1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

area.inner doesn't work with Borders?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does, i changed it to use area.inner now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the mut from area in function parameter and instead create a new variable "inner" to make it look more consistent with popup render code.
If you prefer the previous version i can revert this change.

@SoraTenshi
Copy link
Contributor

Nice job on the PR, has been a staple in my fork for like ever.
Minor bug that i noticed tho: DAP mode (list all variables - Spc g v) does not properly draw the frame.

@ath3
Copy link
Contributor Author

ath3 commented Aug 9, 2023

I cleaned up the code, added popup-borders typable command, and fixed the issues with dap variable popup (thanks @SoraTenshi), and with menu only border setting.

@ath3
Copy link
Contributor Author

ath3 commented Oct 16, 2023

I think this PR is from my perspective in a good state and unless requested i dont plan to do any changes to it.
To celebrate this PR's birthday, can i get a review please?

@ath3
Copy link
Contributor Author

ath3 commented Oct 23, 2023

@the-mikedavis @archseer

Copy link
Member

@dead10ck dead10ck left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your patience on this PR! This is something I'd like to use myself; we just only have so much time to review all the PRs.

Comment on lines 365 to 393
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);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologies, since I'm not super familiar with the rendering code, so I could be misunderstanding something, but this looks like if we want to draw borders around popups that we are deciding not to render the cursor? Why is that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code colors the first and last cell of the selected line in menu.
With borders turned on, the colors would run through the borders.

Comment on lines 279 to 280
let win_height = inner.height as usize - 2 * border;
let len = self.child_size.1 as usize - 2 * border;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we do a saturating_sub here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch

Comment on lines 964 to 965
pub popup_border: bool,
pub menu_border: bool,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could these just be helper methods instead of new fields on the Editor object?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, i changed them

Comment on lines 577 to 616
fn set_borders(
cx: &mut compositor::Context,
args: &[Cow<str>],
event: PromptEvent,
) -> anyhow::Result<()> {
if event != PromptEvent::Validate {
return Ok(());
}

if args.is_empty() {
let borders = (cx.editor.popup_border, cx.editor.menu_border);
cx.editor.set_status(match borders {
(true, true) => "all",
(true, false) => "popup",
(false, true) => "menu",
(false, false) => "none",
});

return Ok(());
}

let arg = args.get(0).context("argument missing")?.to_lowercase();

if let Some(borders) = match arg {
arg if arg.starts_with("all") => Some((true, true)),
arg if arg.starts_with("popup") => Some((true, false)),
arg if arg.starts_with("menu") => Some((false, true)),
arg if arg.starts_with("none") => Some((false, false)),
_ => None,
} {
cx.editor.popup_border = borders.0;
cx.editor.menu_border = borders.1;
} else {
cx.editor
.set_status("Valid options are: none, popup, menu, all");
};

Ok(())
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need its own command? Wouldn't just doing :set popup-border <choice> work?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, i deleted this command now

dead10ck
dead10ck previously approved these changes Oct 24, 2023
Copy link
Member

@dead10ck dead10ck left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok this looks good to me! I tried it out locally too, and it looks good. Thanks for the PR.

@ath3
Copy link
Contributor Author

ath3 commented Nov 27, 2023

Bump

the-mikedavis
the-mikedavis previously approved these changes Dec 11, 2023
Copy link
Member

@the-mikedavis the-mikedavis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me but I'll leave it up to @archseer to merge

Comment on lines +260 to +263
let inner = if self
.contents
.type_name()
.starts_with("helix_term::ui::menu::Menu")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems very hacky to me but I don't see a good way around it - there isn't a way to compare the type to Menu<_> without dealing with strings like this. I think I'm fine with this for now but it's something we should try to eliminate in the future (though it may take a large refactor to the compositor system to do it)

@archseer archseer dismissed stale reviews from the-mikedavis and dead10ck via 6e58c6c December 19, 2023 01:10
@archseer archseer merged commit 9ba691c into helix-editor:master Dec 19, 2023
6 checks passed
dgkf pushed a commit to dgkf/helix that referenced this pull request Jan 30, 2024
mtoohey31 pushed a commit to mtoohey31/helix that referenced this pull request Jun 2, 2024
Vulpesx pushed a commit to Vulpesx/helix that referenced this pull request Jun 7, 2024
smortime pushed a commit to smortime/helix that referenced this pull request Jul 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-helix-term Area: Helix term improvements S-waiting-on-review Status: Awaiting review from a maintainer.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants