forked from NotAShelf/beer
render: OSC 8 hyperlinks with hover/click and a URL hint mode
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I7b39adae426d3fc5b7dfe1437eb10e976a6a6964
This commit is contained in:
parent
72ec651ff1
commit
2161d7250f
6 changed files with 457 additions and 11 deletions
|
|
@ -5,6 +5,8 @@
|
|||
//! then glyphs - so a wide glyph that overflows its cell is not clipped by the
|
||||
//! neighbouring cell's background fill.
|
||||
|
||||
use std::num::NonZeroU16;
|
||||
|
||||
use crate::font::{CellMetrics, Fonts, GlyphData, Style};
|
||||
use crate::grid::{Cell, CursorShape, Flags, Grid, Underline};
|
||||
use crate::theme::{Plane, Rgb, Theme};
|
||||
|
|
@ -94,6 +96,8 @@ pub struct Frame<'a> {
|
|||
pub theme: &'a Theme,
|
||||
pub focused: bool,
|
||||
pub blink_on: bool,
|
||||
/// Hyperlink currently under the pointer; its cells get a hover underline.
|
||||
pub hovered_link: Option<NonZeroU16>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -217,6 +221,10 @@ impl Renderer {
|
|||
}
|
||||
}
|
||||
draw_decorations(&mut canvas, cell, theme, origin_x, row_top, m, fg);
|
||||
// Underline an OSC 8 hyperlink while the pointer hovers over it.
|
||||
if cell.link.is_some() && cell.link == frame.hovered_link {
|
||||
canvas.hline(origin_x, row_top + m.height as i32 - 2, m.width, fg);
|
||||
}
|
||||
}
|
||||
|
||||
// The cursor belongs to the live screen; hide it while scrolled back.
|
||||
|
|
@ -262,6 +270,43 @@ impl Renderer {
|
|||
}
|
||||
}
|
||||
|
||||
/// Draw a URL hint label (e.g. `a`, `bc`) as a highlighted tag starting at
|
||||
/// viewport cell `(row, col)`, over whatever was there.
|
||||
pub fn render_label(
|
||||
&mut self,
|
||||
pixels: &mut [u8],
|
||||
dims: (usize, usize),
|
||||
theme: &Theme,
|
||||
row: usize,
|
||||
col: usize,
|
||||
text: &str,
|
||||
) {
|
||||
let (width, height) = dims;
|
||||
let mut canvas = Canvas {
|
||||
pixels,
|
||||
width,
|
||||
height,
|
||||
};
|
||||
let m = self.fonts.metrics();
|
||||
let (pad_x, pad_y) = self.pad;
|
||||
let row_top = pad_y + row as i32 * m.height as i32;
|
||||
let style = Style {
|
||||
bold: true,
|
||||
italic: false,
|
||||
};
|
||||
let mut x = pad_x + col as i32 * m.width as i32;
|
||||
for c in text.chars() {
|
||||
if x as usize + m.width as usize > width {
|
||||
break;
|
||||
}
|
||||
canvas.fill_rect(x, row_top, m.width, m.height, theme.current_match_bg);
|
||||
if c != ' ' {
|
||||
self.draw_glyph(&mut canvas, c, style, x, row_top, theme.bg);
|
||||
}
|
||||
x += m.width as i32;
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw the IME preedit string inline, starting at grid cell `start_col` of
|
||||
/// row `row`, over whatever was there. The preedit sits on the selection
|
||||
/// background and is underlined so it reads as uncommitted, in-flight text.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue