text_edit: scale the single-line horizontal padding with the field height
The previous commit put the password eye, the caret and the whole multiline layout in physical pixels, but the single-line variant still inset its text by the raw `theme::PAD_H`: 20 physical px whatever the scale. On a scale-2 panel a field 88 px tall, drawn as a pill of radius 44, kept a 20 px inset, so the first glyph sat inside the rounded end while everything else in the field had grown. The padding now follows the field height, like the eye already did: `metrics::single_line_pad_h( rect )` is `PAD_H × rect.height / theme::HEIGHT`, built on `single_line_scale`, which replaces the private `password_toggle_scale` of `draw.rs`. The height is the right reference rather than `canvas.geom_px( PAD_H )`: the inset exists to clear the pill's rounded end, whose radius is half the height. With the default height the two agree, since that height is itself `geom_px( HEIGHT )`; when the app pins the height the padding follows that choice instead of the fluid mode, which on a large surface would push it to 1.5 times the design value next to a field the app deliberately kept smaller. It also needs no canvas, so `password_toggle_hit_zone( rect )` keeps its signature. `draw` resolves the padding once and uses it for the narrowed text rect, the inner clip, the selection band, the placeholder, the text and the caret; `password_toggle_hit_zone` uses it for the half padding beside the eye. `single_line_scroll_x`, `single_line_align_offset` and the single-line branch of `byte_offset_at` use the same helper, so a click still maps to the glyph that was drawn. `hit_test.rs` no longer references `theme` and drops the import. A field `HEIGHT` tall at scale 1 keeps exactly the previous geometry.
This commit is contained in:
@@ -6,7 +6,7 @@ use crate::types::Rect;
|
||||
|
||||
use super::TextEdit;
|
||||
use super::hit_test::{ single_line_align_offset, single_line_scroll_x };
|
||||
use super::metrics::MultilineMetrics;
|
||||
use super::metrics::{ single_line_pad_h, single_line_scale, MultilineMetrics };
|
||||
use super::theme;
|
||||
use super::wrapping::compute_visual_lines;
|
||||
|
||||
@@ -47,15 +47,9 @@ fn rect_intersect( a: Rect, b: Rect ) -> Option<Rect>
|
||||
}
|
||||
}
|
||||
|
||||
// The toggle follows the field height, which is already in physical pixels.
|
||||
fn password_toggle_scale( rect: Rect ) -> f32
|
||||
{
|
||||
rect.height / theme::HEIGHT
|
||||
}
|
||||
|
||||
fn password_toggle_reserve( rect: Rect ) -> f32
|
||||
{
|
||||
( theme::PASSWORD_TOGGLE_SIZE + theme::PASSWORD_TOGGLE_SLOP * 2.0 ) * password_toggle_scale( rect )
|
||||
( theme::PASSWORD_TOGGLE_SIZE + theme::PASSWORD_TOGGLE_SLOP * 2.0 ) * single_line_scale( rect )
|
||||
}
|
||||
|
||||
/// Hit rect for the eye icon at the right edge of a `TextEdit`
|
||||
@@ -67,7 +61,7 @@ fn password_toggle_reserve( rect: Rect ) -> f32
|
||||
pub fn password_toggle_hit_zone( rect: Rect ) -> Rect
|
||||
{
|
||||
let zone_w = ( password_toggle_reserve( rect )
|
||||
+ theme::PAD_H * 0.5 * password_toggle_scale( rect ) ).min( rect.width );
|
||||
+ single_line_pad_h( rect ) * 0.5 ).min( rect.width );
|
||||
Rect
|
||||
{
|
||||
x: rect.x + rect.width - zone_w,
|
||||
@@ -127,9 +121,10 @@ impl<Msg: Clone> TextEdit<Msg>
|
||||
{
|
||||
0.0
|
||||
};
|
||||
let pad_h = single_line_pad_h( rect );
|
||||
let text_rect = Rect
|
||||
{
|
||||
width: ( rect.width - toggle_reserve ).max( theme::PAD_H * 2.0 ),
|
||||
width: ( rect.width - toggle_reserve ).max( pad_h * 2.0 ),
|
||||
..rect
|
||||
};
|
||||
let scroll_x = single_line_scroll_x( canvas, text_rect, &self.value, cursor_pos, secure, font_size );
|
||||
@@ -143,9 +138,9 @@ impl<Msg: Clone> TextEdit<Msg>
|
||||
let outer_clip = canvas.clip_bounds();
|
||||
let inner_rect = Rect
|
||||
{
|
||||
x: rect.x + theme::PAD_H * 0.5,
|
||||
x: rect.x + pad_h * 0.5,
|
||||
y: rect.y,
|
||||
width: ( rect.width - theme::PAD_H - toggle_reserve ).max( 0.0 ),
|
||||
width: ( rect.width - pad_h - toggle_reserve ).max( 0.0 ),
|
||||
height: rect.height,
|
||||
};
|
||||
canvas.set_clip_rects( &interior_clip( &outer_clip, inner_rect ) );
|
||||
@@ -170,7 +165,7 @@ impl<Msg: Clone> TextEdit<Msg>
|
||||
} else {
|
||||
self.value[s..e].to_string()
|
||||
};
|
||||
let x0 = rect.x + theme::PAD_H + align_x - scroll_x
|
||||
let x0 = rect.x + pad_h + align_x - scroll_x
|
||||
+ canvas.measure_text( &prefix_text, font_size );
|
||||
let w = canvas.measure_text( &span_text, font_size );
|
||||
let sel_rect = Rect
|
||||
@@ -191,7 +186,7 @@ impl<Msg: Clone> TextEdit<Msg>
|
||||
);
|
||||
canvas.draw_text(
|
||||
&self.placeholder,
|
||||
rect.x + theme::PAD_H + placeholder_align_x,
|
||||
rect.x + pad_h + placeholder_align_x,
|
||||
text_y,
|
||||
font_size,
|
||||
theme::placeholder(),
|
||||
@@ -199,7 +194,7 @@ impl<Msg: Clone> TextEdit<Msg>
|
||||
} else {
|
||||
canvas.draw_text(
|
||||
&text,
|
||||
rect.x + theme::PAD_H + align_x - scroll_x,
|
||||
rect.x + pad_h + align_x - scroll_x,
|
||||
text_y,
|
||||
font_size,
|
||||
theme::text(),
|
||||
@@ -215,7 +210,7 @@ impl<Msg: Clone> TextEdit<Msg>
|
||||
} else {
|
||||
self.value[..safe_cursor].to_string()
|
||||
};
|
||||
let cursor_x = rect.x + theme::PAD_H + align_x - scroll_x
|
||||
let cursor_x = rect.x + pad_h + align_x - scroll_x
|
||||
+ canvas.measure_text( &cursor_text, font_size );
|
||||
// Caret height follows the text line, not the field box — a
|
||||
// tall field (launcher pill) otherwise grows a caret twice
|
||||
@@ -249,7 +244,7 @@ impl<Msg: Clone> TextEdit<Msg>
|
||||
if let Some( ( visible, _ ) ) = self.password_toggle.as_ref()
|
||||
{
|
||||
let icon_name = if *visible { "actions/invisible" } else { "actions/visible" };
|
||||
let icon_px = ( theme::PASSWORD_TOGGLE_SIZE * password_toggle_scale( rect ) ).round().max( 1.0 ) as u32;
|
||||
let icon_px = ( theme::PASSWORD_TOGGLE_SIZE * single_line_scale( rect ) ).round().max( 1.0 ) as u32;
|
||||
if let Some( ( rgba, iw, ih ) ) = crate::theme::icon_rgba( icon_name, icon_px )
|
||||
{
|
||||
let tinted = crate::theme::tint_symbolic( &rgba, theme::placeholder() );
|
||||
|
||||
Reference in New Issue
Block a user