Skip to content

Commit b28df9f

Browse files
authored
show bboxes (#21)
1 parent fd76c46 commit b28df9f

File tree

3 files changed

+285
-154
lines changed

3 files changed

+285
-154
lines changed

core/gui/src/editor/canvas.rs

Lines changed: 173 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
use std::collections::VecDeque;
22

33
use compiler::compile::{SolvedValue, ifmatvec};
4+
use enumify::enumify;
45
use geometry::transform::TransformationMatrix;
56
use gpui::{
67
BorderStyle, Bounds, Context, Corners, DefiniteLength, DragMoveEvent, Edges, Element, Entity,
78
InteractiveElement, IntoElement, Length, MouseButton, MouseDownEvent, MouseMoveEvent,
8-
MouseUpEvent, PaintQuad, ParentElement, Pixels, Point, Render, ScrollWheelEvent, Size, Style,
9-
Styled, Subscription, Window, div, pattern_slash, rgb, rgba, solid_background,
9+
MouseUpEvent, PaintQuad, ParentElement, Pixels, Point, Render, Rgba, ScrollWheelEvent, Size,
10+
Style, Styled, Subscription, Window, div, pattern_slash, rgb, rgba, solid_background,
1011
};
1112
use itertools::Itertools;
1213

@@ -19,11 +20,18 @@ pub enum ShapeFill {
1920
}
2021

2122
#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
22-
pub struct RectId {
23+
pub struct ElementId {
2324
scope: ScopeAddress,
2425
idx: usize,
2526
}
2627

28+
#[enumify]
29+
#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
30+
pub enum RectId {
31+
Element(ElementId),
32+
Scope(ScopeAddress),
33+
}
34+
2735
#[derive(Clone, PartialEq)]
2836
pub struct Rect {
2937
pub x0: f32,
@@ -62,6 +70,7 @@ pub struct LayoutCanvas {
6270
#[allow(unused)]
6371
subscriptions: Vec<Subscription>,
6472
rects: Vec<(Rect, LayerState)>,
73+
scope_rects: Vec<Rect>,
6574
}
6675

6776
impl IntoElement for CanvasElement {
@@ -72,6 +81,46 @@ impl IntoElement for CanvasElement {
7281
}
7382
}
7483

84+
fn get_paint_quad(
85+
r: &Rect,
86+
bounds: Bounds<Pixels>,
87+
scale: f32,
88+
offset: Point<Pixels>,
89+
fill: ShapeFill,
90+
color: Rgba,
91+
border_color: Rgba,
92+
) -> Option<PaintQuad> {
93+
let rect_bounds = Bounds::new(
94+
Point::new(scale * Pixels(r.x0), scale * Pixels(r.y0)) + offset + bounds.origin,
95+
Size::new(scale * Pixels(r.x1 - r.x0), scale * Pixels(r.y1 - r.y0)),
96+
);
97+
let background = match fill {
98+
ShapeFill::Solid => solid_background(color),
99+
ShapeFill::Stippling => pattern_slash(color.into(), 1., 9.),
100+
};
101+
if let Some(clipped) = intersect(&rect_bounds, &bounds) {
102+
let left_border = f32::clamp((rect_bounds.left().0 + 2.) - bounds.left().0, 0., 2.);
103+
let right_border = f32::clamp(bounds.right().0 - (rect_bounds.right().0 - 2.), 0., 2.);
104+
let top_border = f32::clamp((rect_bounds.top().0 + 2.) - bounds.top().0, 0., 2.);
105+
let bot_border = f32::clamp(bounds.bottom().0 - (rect_bounds.bottom().0 - 2.), 0., 2.);
106+
let mut border_widths = Edges::all(Pixels(2.));
107+
border_widths.left = Pixels(left_border);
108+
border_widths.right = Pixels(right_border);
109+
border_widths.top = Pixels(top_border);
110+
border_widths.bottom = Pixels(bot_border);
111+
Some(PaintQuad {
112+
bounds: clipped,
113+
corner_radii: Corners::all(Pixels(0.)),
114+
background,
115+
border_widths,
116+
border_color: border_color.into(),
117+
border_style: BorderStyle::Solid,
118+
})
119+
} else {
120+
None
121+
}
122+
}
123+
75124
impl Element for CanvasElement {
76125
type RequestLayoutState = ();
77126
type PrepaintState = ();
@@ -125,6 +174,7 @@ impl Element for CanvasElement {
125174
let layers = &inner.state.read(cx).layers.read(cx);
126175

127176
let mut rects = Vec::new();
177+
let mut scope_rects = Vec::new();
128178
if let Some(solved_cell) = solved_cell {
129179
let mut queue = VecDeque::from_iter([(
130180
solved_cell.selected_scope,
@@ -134,9 +184,21 @@ impl Element for CanvasElement {
134184
while let Some((curr_address @ ScopeAddress { scope, cell }, mat, ofs)) =
135185
queue.pop_front()
136186
{
137-
let scope_info = &solved_cell.output.cells[&cell].scopes[&scope];
138-
let visible = solved_cell.state[&curr_address].visible;
139-
if !visible {
187+
let cell_info = &solved_cell.output.cells[&cell];
188+
let scope_info = &cell_info.scopes[&scope];
189+
let scope_state = &solved_cell.state[&curr_address];
190+
if !scope_state.visible {
191+
if let Some(bbox) = &scope_state.bbox {
192+
let p0p = ifmatvec(mat, (bbox.x0, bbox.y0));
193+
let p1p = ifmatvec(mat, (bbox.x1, bbox.y1));
194+
scope_rects.push(Rect {
195+
x0: (p0p.0.min(p1p.0) + ofs.0) as f32,
196+
y0: (p0p.1.min(p1p.1) + ofs.1) as f32,
197+
x1: (p0p.0.max(p1p.0) + ofs.0) as f32,
198+
y1: (p0p.1.max(p1p.1) + ofs.1) as f32,
199+
id: RectId::Scope(curr_address),
200+
});
201+
}
140202
continue;
141203
}
142204
for (i, value) in scope_info.elts.iter().enumerate() {
@@ -157,10 +219,10 @@ impl Element for CanvasElement {
157219
y0: (p0p.1.min(p1p.1) + ofs.1) as f32,
158220
x1: (p0p.0.max(p1p.0) + ofs.0) as f32,
159221
y1: (p0p.1.max(p1p.1) + ofs.1) as f32,
160-
id: RectId {
222+
id: RectId::Element(ElementId {
161223
scope: curr_address,
162224
idx: i,
163-
},
225+
}),
164226
},
165227
layer.clone(),
166228
));
@@ -178,11 +240,27 @@ impl Element for CanvasElement {
178240
scope: solved_cell.output.cells[&inst.cell].root,
179241
cell: inst.cell,
180242
};
181-
queue.push_back((
182-
inst_address,
183-
mat * inst_mat,
184-
(inst_ofs.0 + ofs.0, inst_ofs.1 + ofs.1),
185-
));
243+
let new_mat = mat * inst_mat;
244+
let new_ofs = (inst_ofs.0 + ofs.0, inst_ofs.1 + ofs.1);
245+
let scope_state = &solved_cell.state[&inst_address];
246+
if !scope_state.visible {
247+
if let Some(bbox) = &scope_state.bbox {
248+
let p0p = ifmatvec(new_mat, (bbox.x0, bbox.y0));
249+
let p1p = ifmatvec(new_mat, (bbox.x1, bbox.y1));
250+
scope_rects.push(Rect {
251+
x0: (p0p.0.min(p1p.0) + new_ofs.0) as f32,
252+
y0: (p0p.1.min(p1p.1) + new_ofs.1) as f32,
253+
x1: (p0p.0.max(p1p.0) + new_ofs.0) as f32,
254+
y1: (p0p.1.max(p1p.1) + new_ofs.1) as f32,
255+
id: RectId::Element(ElementId {
256+
scope: curr_address,
257+
idx: i,
258+
}),
259+
});
260+
}
261+
continue;
262+
}
263+
queue.push_back((inst_address, new_mat, new_ofs));
186264
}
187265
_ => {}
188266
}
@@ -208,60 +286,61 @@ impl Element for CanvasElement {
208286
.clone()
209287
.paint(bounds, window, cx, |window, _cx| {
210288
window.paint_layer(bounds, |window| {
289+
let mut selected_quads = Vec::new();
211290
for (r, l) in &rects {
212-
let rect_bounds = Bounds::new(
213-
Point::new(scale * Pixels(r.x0), scale * Pixels(r.y0))
214-
+ offset
215-
+ bounds.origin,
216-
Size::new(scale * Pixels(r.x1 - r.x0), scale * Pixels(r.y1 - r.y0)),
217-
);
218-
let background = match l.fill {
219-
ShapeFill::Solid => solid_background(l.color),
220-
ShapeFill::Stippling => pattern_slash(l.color.into(), 1., 9.),
221-
};
222-
if let Some(clipped) = intersect(&rect_bounds, &bounds) {
223-
let left_border =
224-
f32::clamp((rect_bounds.left().0 + 2.) - bounds.left().0, 0., 2.);
225-
let right_border =
226-
f32::clamp(bounds.right().0 - (rect_bounds.right().0 - 2.), 0., 2.);
227-
let top_border =
228-
f32::clamp((rect_bounds.top().0 + 2.) - bounds.top().0, 0., 2.);
229-
let bot_border = f32::clamp(
230-
bounds.bottom().0 - (rect_bounds.bottom().0 - 2.),
231-
0.,
232-
2.,
233-
);
234-
let mut border_widths = Edges::all(Pixels(2.));
235-
border_widths.left = Pixels(left_border);
236-
border_widths.right = Pixels(right_border);
237-
border_widths.top = Pixels(top_border);
238-
border_widths.bottom = Pixels(bot_border);
239-
window.paint_quad(PaintQuad {
240-
bounds: clipped,
241-
corner_radii: Corners::all(Pixels(0.)),
242-
background,
243-
border_widths,
244-
border_color: l.border_color.into(),
245-
border_style: BorderStyle::Solid,
246-
});
291+
if let Some(quad) = get_paint_quad(
292+
r,
293+
bounds,
294+
scale,
295+
offset,
296+
l.fill,
297+
l.color,
298+
l.border_color,
299+
) {
300+
window.paint_quad(quad.clone());
247301
if let Some(selected_rect) = selected_rect
248302
&& r.id == selected_rect
249303
{
250-
window.paint_quad(PaintQuad {
251-
bounds: clipped,
252-
corner_radii: Corners::all(Pixels(0.)),
304+
selected_quads.push(PaintQuad {
253305
background: solid_background(rgba(0)),
254-
border_widths,
255306
border_color: rgb(0xffff00).into(),
256307
border_style: BorderStyle::Solid,
308+
..quad
257309
});
258310
}
259311
}
260312
}
313+
for r in &scope_rects {
314+
if let Some(quad) = get_paint_quad(
315+
r,
316+
bounds,
317+
scale,
318+
offset,
319+
ShapeFill::Solid,
320+
rgba(0),
321+
rgba(0xffffffff),
322+
) {
323+
window.paint_quad(quad.clone());
324+
if let Some(selected_rect) = selected_rect
325+
&& r.id == selected_rect
326+
{
327+
selected_quads.push(PaintQuad {
328+
background: solid_background(rgba(0)),
329+
border_color: rgb(0xffff00).into(),
330+
border_style: BorderStyle::Solid,
331+
..quad
332+
});
333+
}
334+
}
335+
}
336+
for q in selected_quads {
337+
window.paint_quad(q);
338+
}
261339
})
262340
});
263341
self.inner.update(cx, |inner, cx| {
264342
inner.rects = rects;
343+
inner.scope_rects = scope_rects;
265344
cx.notify();
266345
});
267346
}
@@ -310,6 +389,7 @@ impl LayoutCanvas {
310389
subscriptions: vec![cx.observe(state, |_, _, cx| cx.notify())],
311390
state: state.clone(),
312391
rects: Vec::new(),
392+
scope_rects: Vec::new(),
313393
}
314394
}
315395

@@ -322,47 +402,60 @@ impl LayoutCanvas {
322402
let rects = self
323403
.rects
324404
.iter()
325-
.cloned()
405+
.rev()
326406
.sorted_by_key(|(_, layer)| usize::MAX - layer.z)
327-
.collect_vec();
407+
.map(|(r, _)| r);
328408
let scale = self.scale;
329409
let offset = self.offset;
330-
for (r, _) in rects {
410+
let mut selected_rect = None;
411+
for r in rects.chain(self.scope_rects.iter()) {
331412
let rect_bounds = Bounds::new(
332413
Point::new(scale * Pixels(r.x0), scale * Pixels(r.y0))
333414
+ offset
334415
+ self.screen_origin,
335416
Size::new(scale * Pixels(r.x1 - r.x0), scale * Pixels(r.y1 - r.y0)),
336417
);
337418
if rect_bounds.contains(&event.position) {
338-
self.state.update(cx, |state, cx| {
339-
state.solved_cell.update(cx, |cell, cx| {
340-
if let Some(cell) = cell.as_mut() {
341-
cell.selected_rect = Some(r.id);
342-
state.lsp_client.select_rect(
343-
cell.output.cells[&r.id.scope.cell].scopes[&r.id.scope.scope].elts
344-
[r.id.idx]
345-
.as_ref()
346-
.unwrap_rect()
347-
.source
348-
.as_ref()
349-
.map(|source| (cell.file.clone(), source.span)),
350-
);
351-
cx.notify();
352-
}
353-
});
354-
});
355-
return;
419+
selected_rect = Some(r);
356420
}
357421
}
358-
self.state.update(cx, |state, cx| {
359-
state.solved_cell.update(cx, |cell, cx| {
360-
if let Some(cell) = cell.as_mut() {
361-
cell.selected_rect = None;
362-
cx.notify();
363-
}
422+
if let Some(r) = selected_rect.cloned() {
423+
self.state.update(cx, |state, cx| {
424+
state.solved_cell.update(cx, |cell, cx| {
425+
if let Some(cell) = cell.as_mut() {
426+
cell.selected_rect = Some(r.id);
427+
let args = match r.id {
428+
RectId::Element(id) => {
429+
match &cell.output.cells[&id.scope.cell].scopes[&id.scope.scope]
430+
.elts[id.idx]
431+
{
432+
SolvedValue::Rect(r) => r
433+
.source
434+
.as_ref()
435+
.map(|source| (cell.file.clone(), source.span)),
436+
_ => None,
437+
}
438+
}
439+
RectId::Scope(id) => Some((
440+
cell.file.clone(),
441+
cell.output.cells[&id.cell].scopes[&id.scope].span,
442+
)),
443+
};
444+
state.lsp_client.select_rect(args);
445+
cx.notify();
446+
}
447+
});
364448
});
365-
});
449+
} else {
450+
self.state.update(cx, |state, cx| {
451+
state.solved_cell.update(cx, |cell, cx| {
452+
if let Some(cell) = cell.as_mut() {
453+
cell.selected_rect = None;
454+
cx.notify();
455+
}
456+
});
457+
});
458+
}
366459
}
367460

368461
#[allow(unused)]

0 commit comments

Comments
 (0)