Ported examples 00 and 01 to proc macro interface.
This commit is contained in:
@@ -114,7 +114,7 @@ impl PointerRouter {
|
||||
|
||||
match event.kind {
|
||||
PointerEventKind::Move => {
|
||||
if let Some(target) = hit_target.clone() {
|
||||
if let Some(target) = self.pressed.clone().or(hit_target.clone()) {
|
||||
routed.push(RoutedPointerEvent {
|
||||
kind: RoutedPointerEventKind::Move,
|
||||
target,
|
||||
@@ -314,6 +314,36 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn router_prefers_pressed_target_on_pointer_move() {
|
||||
let mut router = PointerRouter::new();
|
||||
let tree = interaction_tree();
|
||||
let _ = router.route(
|
||||
&tree,
|
||||
PointerEvent::new(
|
||||
0,
|
||||
Point::new(20.0, 20.0),
|
||||
PointerEventKind::Down {
|
||||
button: PointerButton::Primary,
|
||||
},
|
||||
),
|
||||
);
|
||||
let routed = router.route(
|
||||
&tree,
|
||||
PointerEvent::new(0, Point::new(160.0, 20.0), PointerEventKind::Move),
|
||||
);
|
||||
|
||||
assert!(
|
||||
routed
|
||||
.iter()
|
||||
.any(|event| event.kind == RoutedPointerEventKind::Move)
|
||||
);
|
||||
assert_eq!(
|
||||
routed.last().unwrap().target.element_id,
|
||||
Some(ElementId::new(1))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn router_routes_scroll_to_deepest_hover_target() {
|
||||
let mut router = PointerRouter::new();
|
||||
|
||||
@@ -585,6 +585,7 @@ impl SceneSnapshot {
|
||||
mod tests {
|
||||
use super::{Color, Point, PreparedText, Rect};
|
||||
use crate::TextSelectionStyle;
|
||||
use crate::{TextStyle, TextSystem, TextWrap};
|
||||
|
||||
#[test]
|
||||
fn prepared_text_hit_testing_clamps_to_nearest_cluster_boundary() {
|
||||
@@ -703,4 +704,22 @@ mod tests {
|
||||
assert_eq!(text.line_start_offset(6), Some(4));
|
||||
assert_eq!(text.line_end_offset(2), Some(4));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn prepared_text_multiline_selection_stays_on_target_line() {
|
||||
let mut text_system = TextSystem::new();
|
||||
let style = TextStyle::new(16.0, Color::rgb(0xFF, 0xFF, 0xFF)).with_wrap(TextWrap::None);
|
||||
let text = text_system.prepare("ab\ncd\nef", Point::new(10.0, 20.0), &style);
|
||||
|
||||
assert_eq!(text.lines.len(), 3);
|
||||
|
||||
let target_line = &text.lines[1];
|
||||
let y = target_line.rect.origin.y + target_line.rect.size.height * 0.5;
|
||||
let start = text.byte_offset_for_position(Point::new(target_line.rect.origin.x, y));
|
||||
let end = text.byte_offset_for_position(Point::new(target_line.rect.origin.x + 16.0, y));
|
||||
let rects = text.selection_rects(start, end);
|
||||
|
||||
assert_eq!(rects.len(), 1);
|
||||
assert_eq!(rects[0].origin.y, target_line.rect.origin.y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -418,6 +418,7 @@ impl TextSystem {
|
||||
}
|
||||
self.frame_stats.buffer_build_ms += buffer_build_started.elapsed().as_secs_f64() * 1_000.0;
|
||||
|
||||
let line_starts = line_start_offsets(&combined_text(spans));
|
||||
let mut measured_width: f32 = 0.0;
|
||||
let mut measured_height: f32 = 0.0;
|
||||
let mut lines = Vec::new();
|
||||
@@ -430,6 +431,7 @@ impl TextSystem {
|
||||
measured_width = measured_width.max(run.line_w);
|
||||
measured_height = measured_height.max(run.line_top + run.line_height);
|
||||
let x_offset = aligned_line_offset(style.align, width, run.line_w);
|
||||
let line_offset = line_starts.get(run.line_i).copied().unwrap_or(0);
|
||||
let glyph_start = glyphs.len();
|
||||
glyphs.extend(run.glyphs.iter().map(move |glyph| {
|
||||
let physical = glyph.physical((x_offset, run.line_y), 1.0);
|
||||
@@ -438,13 +440,19 @@ impl TextSystem {
|
||||
advance: glyph.w,
|
||||
color: glyph.color_opt.map_or(style.color, color_from_cosmic),
|
||||
cache_key: Some(physical.cache_key),
|
||||
text_start: glyph.start,
|
||||
text_end: glyph.end,
|
||||
text_start: line_offset + glyph.start,
|
||||
text_end: line_offset + glyph.end,
|
||||
}
|
||||
}));
|
||||
let glyph_end = glyphs.len();
|
||||
let text_start = run.glyphs.first().map_or(0, |glyph| glyph.start);
|
||||
let text_end = run.glyphs.last().map_or(text_start, |glyph| glyph.end);
|
||||
let text_start = run
|
||||
.glyphs
|
||||
.first()
|
||||
.map_or(line_offset, |glyph| line_offset + glyph.start);
|
||||
let text_end = run
|
||||
.glyphs
|
||||
.last()
|
||||
.map_or(text_start, |glyph| line_offset + glyph.end);
|
||||
lines.push(PreparedTextLine {
|
||||
rect: Rect::new(x_offset, run.line_top, run.line_w.max(0.0), run.line_height),
|
||||
text_start,
|
||||
@@ -504,6 +512,28 @@ fn combined_text(spans: &[TextSpan]) -> String {
|
||||
text
|
||||
}
|
||||
|
||||
fn line_start_offsets(text: &str) -> Vec<usize> {
|
||||
let mut starts = vec![0];
|
||||
let bytes = text.as_bytes();
|
||||
let mut index = 0;
|
||||
while index < bytes.len() {
|
||||
match bytes[index] {
|
||||
b'\n' => starts.push(index + 1),
|
||||
b'\r' => {
|
||||
if bytes.get(index + 1) == Some(&b'\n') {
|
||||
starts.push(index + 2);
|
||||
index += 1;
|
||||
} else {
|
||||
starts.push(index + 1);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
index += 1;
|
||||
}
|
||||
starts
|
||||
}
|
||||
|
||||
fn layout_cache_key(
|
||||
spans: &[TextSpan],
|
||||
style: &TextStyle,
|
||||
|
||||
Reference in New Issue
Block a user