use std::sync::Arc;
use egui::{Pos2, Rect, Stroke, StrokeKind, Ui};
use epaint::{pos2, Galley};
use crate::style::{CodeBlockStyle, HorizontalRuleStyle};
pub fn compute_code_block_rects(ui: &mut Ui, code_blocks: &[(usize, usize)], galley: &Arc<Galley>) -> Vec<Rect> {
let mut code_block_rects = Vec::new();
let available_width = ui.available_width() - 16.0;
for &(start, end) in code_blocks {
debug_assert!(start <= end);
let mut start_row = None;
let mut offset = 0;
for (row_index, row) in galley.rows.iter().enumerate() {
let row_range = offset..=offset + row.char_count_including_newline();
if row_range.contains(&start) {
start_row = Some(row_index);
}
if let Some(start_row) = start_row {
if row_range.contains(&end) || row_index == galley.rows.len() - 1 {
let mut bg_rect = Rect::from_min_max(galley.rows[start_row].rect().min, row.rect().max);
bg_rect.set_width(available_width);
code_block_rects.push(bg_rect);
break;
}
}
offset += row.char_count_including_newline();
}
}
code_block_rects
}
pub fn paint_code_block_bg(ui: &Ui, bg_rect: Rect, origin: Pos2, code_style: &CodeBlockStyle) {
let mut r = bg_rect.translate(origin.to_vec2());
r.min.x -= code_style.padding[0];
r.min.y -= code_style.padding[1];
r.max.x += code_style.padding[2];
r.max.y += code_style.padding[3];
let stroke = Stroke::new(code_style.stroke_width, ui.visuals().widgets.noninteractive.bg_stroke.color);
ui.painter().rect_stroke(r, code_style.corner_radius, stroke, StrokeKind::Inside);
}
pub fn paint_horizontal_rules(
ui: &Ui,
hr_positions: &[usize],
galley: &Arc<Galley>,
origin: Pos2,
available_width: f32,
hr_style: &HorizontalRuleStyle,
) {
if hr_positions.is_empty() {
return;
}
let stroke = Stroke::new(hr_style.stroke_width, ui.visuals().widgets.noninteractive.bg_stroke.color);
for &hr_char in hr_positions {
let mut offset = 0;
for row in &galley.rows {
let row_end = offset + row.char_count_including_newline();
if hr_char >= offset && hr_char < row_end {
let y = origin.y + (row.min_y() + row.max_y()) / 2.0;
ui.painter().line_segment([pos2(origin.x, y), pos2(origin.x + available_width, y)], stroke);
break;
}
offset = row_end;
}
}
}