ltk/widget/text_edit/
gutter.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// SPDX-License-Identifier: LGPL-2.1-only
// Copyright (C) 2026 Liberux Labs, S. L. <info@liberux.net>

//! The column of line numbers at the left of a multiline field.

use crate::render::Canvas;
use crate::types::Rect;

use super::metrics::MultilineMetrics;
use super::theme;
use super::TextFont;

pub( crate ) fn line_count( value: &str ) -> usize
{
	value.bytes().filter( |&b| b == b'\n' ).count() + 1
}

/// The width of `label` in the face the numbers are drawn in: the monospace one, else the field's.
pub( crate ) fn measure( canvas: &Canvas, label: &str, font_size: f32 ) -> f32
{
	match crate::system_fonts::monospace()
	{
		Some( mono ) => canvas.measure_text_with_font( label, font_size, &mono ),
		None         => canvas.measure_text( label, font_size ),
	}
}

/// Wide enough for the number of the last line, with the gap before it.
pub( crate ) fn width( canvas: &Canvas, value: &str, font: &TextFont ) -> f32
{
	let font_size = MultilineMetrics::resolve( canvas, font.size ).font_size;
	let digits    = "0".repeat( line_count( value ).to_string().len() );
	measure( canvas, &digits, font_size ) + canvas.geom_px( theme::GUTTER_PAD )
}

/// Where the text of a field `rect` goes: right of the line numbers when it shows them.
pub( crate ) fn text_rect( canvas: &Canvas, rect: Rect, value: &str, font: &TextFont, line_numbers: bool ) -> Rect
{
	if !line_numbers { return rect; }
	let width = width( canvas, value, font ).min( rect.width );
	Rect { x: rect.x + width, width: rect.width - width, ..rect }
}