Skip to content

Commit c3ecaf5

Browse files
author
Tom
committed
implement buggy click-to-edit-dimension
1 parent 0812ecc commit c3ecaf5

File tree

4 files changed

+169
-52
lines changed

4 files changed

+169
-52
lines changed

detailer/src/lib.rs

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use drawing::Handler;
22
use drawing::{handler::ToolResponse, tools, Data, Feature, FeatureKey, FeatureMeta};
3-
use drawing::{Constraint, ConstraintKey, DimensionDisplay};
3+
use drawing::{Constraint, ConstraintKey, ConstraintMeta, DimensionDisplay};
44

55
#[derive(Debug, Default, Clone, PartialEq)]
66
pub enum Tab {
@@ -77,7 +77,17 @@ impl<'a> Widget<'a> {
7777
fn show_selection_tab(&mut self, ui: &mut egui::Ui) {
7878
let mut commands: Vec<ToolResponse> = Vec::with_capacity(4);
7979
let mut changed = false;
80-
let selected: Vec<FeatureKey> = self.drawing.selected_map.keys().map(|k| *k).collect();
80+
let mut selected: Vec<FeatureKey> = self.drawing.selected_map.keys().map(|k| *k).collect();
81+
82+
if let Some(ck) = self.drawing.selected_constraint {
83+
if let Some(c) = self.drawing.constraints.get(ck) {
84+
for fk in c.affecting_features() {
85+
if !selected.contains(&fk) {
86+
selected.push(fk);
87+
}
88+
}
89+
}
90+
};
8191

8292
egui::ScrollArea::vertical().show(ui, |ui| {
8393
for k in selected {
@@ -110,7 +120,7 @@ impl<'a> Widget<'a> {
110120
.default_open(true)
111121
.show(ui, |ui| {
112122
for ck in constraints {
113-
match self.drawing.constraint_mut(ck) {
123+
ui.push_id(k, |ui| match self.drawing.constraint_mut(ck) {
114124
Some(Constraint::Fixed(_, _, x, y)) => {
115125
Widget::show_constraint_fixed(
116126
ui,
@@ -121,14 +131,15 @@ impl<'a> Widget<'a> {
121131
y,
122132
)
123133
}
124-
Some(Constraint::LineLength(_, _, d, dd)) => {
134+
Some(Constraint::LineLength(meta, _, d, dd)) => {
125135
Widget::show_constraint_line_length(
126136
ui,
127137
&mut commands,
128138
&mut changed,
129139
&ck,
130140
d,
131141
dd,
142+
meta,
132143
)
133144
}
134145
Some(Constraint::LineAlongCardinal(
@@ -143,7 +154,7 @@ impl<'a> Widget<'a> {
143154
is_horizontal,
144155
),
145156
None => {}
146-
}
157+
});
147158
}
148159
});
149160
}
@@ -195,6 +206,7 @@ impl<'a> Widget<'a> {
195206
k: &ConstraintKey,
196207
d: &mut f32,
197208
_ref_pt: &mut DimensionDisplay,
209+
meta: &mut ConstraintMeta,
198210
) {
199211
ui.horizontal(|ui| {
200212
let r = ui.available_size();
@@ -203,9 +215,14 @@ impl<'a> Widget<'a> {
203215
let text_rect = ui.add(egui::Label::new("Length").wrap(false)).rect;
204216
ui.add_space(r.x / 2. - text_rect.width() - ui.spacing().item_spacing.x);
205217

206-
*changed |= ui
207-
.add_sized([50., text_height * 1.4], egui::DragValue::new(d))
208-
.changed();
218+
let dv = ui.add_sized([50., text_height * 1.4], egui::DragValue::new(d));
219+
if meta.focus_to {
220+
meta.focus_to = false;
221+
dv.request_focus();
222+
ui.memory_mut(|mem| mem.request_focus(dv.id));
223+
} else {
224+
*changed |= dv.changed();
225+
}
209226

210227
if *changed && *d < 0. {
211228
*d = 0.;

drawing/src/constraints.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ slotmap::new_key_type! {
88
}
99

1010
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize, PartialEq)]
11-
pub struct ConstraintMeta {}
11+
pub struct ConstraintMeta {
12+
#[serde(skip)]
13+
pub focus_to: bool,
14+
}
1215

1316
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize, PartialEq)]
1417
pub struct DimensionDisplay {

drawing/src/data/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ pub struct Data {
3333
pub vp: Viewport,
3434

3535
pub selected_map: HashMap<FeatureKey, usize>,
36+
#[serde(skip)]
37+
pub selected_constraint: Option<ConstraintKey>,
3638

3739
pub terms: TermAllocator,
3840
}
@@ -44,6 +46,7 @@ impl Default for Data {
4446
constraints: ConstraintData::default(),
4547
vp: Viewport::default(),
4648
selected_map: HashMap::default(),
49+
selected_constraint: None,
4750
terms: TermAllocator::default(),
4851
}
4952
}

drawing/src/lib.rs

Lines changed: 137 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,15 @@ enum DragState {
3939
SelectBox(egui::Pos2),
4040
Feature(FeatureKey, egui::Vec2),
4141
Constraint(ConstraintKey, egui::Vec2),
42+
EditingLineLength(ConstraintKey),
4243
}
4344

4445
#[derive(Clone, Debug, Copy)]
4546
enum Input {
4647
Selection(egui::Rect),
4748
FeatureDrag(FeatureKey, egui::Pos2),
4849
ConstraintDrag(ConstraintKey, egui::Pos2),
50+
EditingLineLength(ConstraintKey),
4951
}
5052

5153
/// Widget implements the egui drawing widget.
@@ -113,44 +115,78 @@ impl<'a> Widget<'a> {
113115
// Handle: selection, dragging
114116
let current_input = if let Some(hp) = hp {
115117
let select_id = ui.make_persistent_id("select_box_start");
116-
let drag_state = if response.drag_started_by(egui::PointerButton::Primary) {
117-
match hover {
118-
// dragging a box to select
119-
Hover::None => {
120-
let state = DragState::SelectBox(self.drawing.vp.screen_to_point(hp));
121-
ui.memory_mut(|mem| mem.data.insert_temp(select_id, state));
122-
Some(state)
123-
}
124-
// Dragging a point
118+
let drag_state = match (
119+
hover,
120+
response.drag_started_by(egui::PointerButton::Primary),
121+
response.double_clicked_by(egui::PointerButton::Primary),
122+
) {
123+
// dragging a box to select
124+
(Hover::None, true, false) => {
125+
let state = DragState::SelectBox(self.drawing.vp.screen_to_point(hp));
126+
ui.memory_mut(|mem| mem.data.insert_temp(select_id, state));
127+
Some(state)
128+
}
129+
// Dragging a point
130+
(
125131
Hover::Feature {
126132
k,
127133
feature: Feature::Point(_, px, py),
128-
} => {
129-
let offset =
130-
self.drawing.vp.screen_to_point(hp) - egui::Pos2::new(*px, *py);
131-
let state = DragState::Feature(*k, offset);
132-
ui.memory_mut(|mem| mem.data.insert_temp(select_id, state));
133-
Some(state)
134-
}
135-
// TODO: dragging a line
134+
},
135+
true,
136+
false,
137+
) => {
138+
let offset = self.drawing.vp.screen_to_point(hp) - egui::Pos2::new(*px, *py);
139+
let state = DragState::Feature(*k, offset);
140+
ui.memory_mut(|mem| mem.data.insert_temp(select_id, state));
141+
Some(state)
142+
}
143+
// TODO: dragging a line
144+
(
136145
Hover::Feature {
137146
k: _,
138147
feature: Feature::LineSegment(..),
139-
} => None,
148+
},
149+
true,
150+
false,
151+
) => None,
152+
// Dragging a LineLength constraint reference
153+
(
140154
Hover::Constraint {
141155
k,
142156
constraint: Constraint::LineLength(_, _, _, dd),
143-
} => {
144-
let offset =
145-
self.drawing.vp.screen_to_point(hp) - egui::Pos2::new(dd.x, dd.y);
146-
let state = DragState::Constraint(*k, offset);
147-
ui.memory_mut(|mem| mem.data.insert_temp(select_id, state));
157+
},
158+
true,
159+
false,
160+
) => {
161+
let offset = self.drawing.vp.screen_to_point(hp) - egui::Pos2::new(dd.x, dd.y);
162+
let state = DragState::Constraint(*k, offset);
163+
ui.memory_mut(|mem| mem.data.insert_temp(select_id, state));
164+
Some(state)
165+
}
166+
// Double-clicking a LineLength constraint reference
167+
(
168+
Hover::Constraint {
169+
k,
170+
constraint: Constraint::LineLength(_, _, _, dd),
171+
},
172+
false,
173+
true,
174+
) => {
175+
if let Some(Constraint::LineLength(meta, ..)) = self.drawing.constraint_mut(*k)
176+
{
177+
meta.focus_to = true;
178+
let state = DragState::EditingLineLength(*k);
179+
ui.memory_mut(|mem| {
180+
mem.data.insert_temp(select_id, state);
181+
});
148182
Some(state)
183+
} else {
184+
unreachable!();
149185
}
150-
Hover::Constraint { .. } => None,
151186
}
152-
} else {
153-
ui.memory(|mem| mem.data.get_temp(select_id))
187+
(Hover::Constraint { .. }, true, false) => None,
188+
189+
(_, _, _) => ui.memory(|mem| mem.data.get_temp(select_id)),
154190
};
155191

156192
let released = response.drag_released_by(egui::PointerButton::Primary);
@@ -196,20 +232,37 @@ impl<'a> Widget<'a> {
196232
Some(Input::ConstraintDrag(ck, hp))
197233
}
198234

235+
(Some(DragState::EditingLineLength(ck)), _) => {
236+
if response.clicked() && matches!(hover, Hover::None) {
237+
ui.memory_mut(|mem| mem.data.remove::<DragState>(select_id));
238+
}
239+
Some(Input::EditingLineLength(ck))
240+
}
241+
199242
(None, _) => None,
200243
}
201244
} else {
202245
None
203246
};
204247

248+
self.drawing.selected_constraint = if let Some(Input::EditingLineLength(ck)) = current_input
249+
{
250+
Some(ck)
251+
} else {
252+
None
253+
};
254+
205255
// All clicks get keyboard focus.
206256
// println!("focus-w: {:?}", response.ctx.memory(|mem| mem.focus()));
207257
if response.clicked() && !response.lost_focus() {
208258
ui.memory_mut(|mem| mem.request_focus(response.id));
209259
}
210260

211261
// Handle: clicks altering selection
212-
if hp.is_some() && response.clicked_by(egui::PointerButton::Primary) {
262+
if hp.is_some()
263+
&& response.clicked_by(egui::PointerButton::Primary)
264+
&& !matches!(current_input, Some(Input::EditingLineLength(ck)))
265+
{
213266
let shift_held = ui.input(|i| i.modifiers.shift);
214267

215268
// feature clicked: add-to or replace selection
@@ -308,25 +361,66 @@ impl<'a> Widget<'a> {
308361
v.paint(self.drawing, k, &pp, painter);
309362
}
310363

311-
if let Some(Input::Selection(current_drag)) = current_input {
312-
let screen_rect = self.drawing.vp.translate_rect(current_drag);
313-
painter.rect_filled(
314-
screen_rect.shrink(1.),
315-
egui::Rounding::ZERO,
316-
egui::Color32::from_white_alpha(20),
317-
);
318-
painter.rect_stroke(
319-
screen_rect,
320-
egui::Rounding::ZERO,
321-
egui::Stroke {
322-
width: 1.,
323-
color: egui::Color32::WHITE,
324-
},
325-
);
326-
}
364+
match current_input {
365+
Some(Input::Selection(current_drag)) => {
366+
let screen_rect = self.drawing.vp.translate_rect(current_drag);
367+
painter.rect_filled(
368+
screen_rect.shrink(1.),
369+
egui::Rounding::ZERO,
370+
egui::Color32::from_white_alpha(20),
371+
);
372+
painter.rect_stroke(
373+
screen_rect,
374+
egui::Rounding::ZERO,
375+
egui::Stroke {
376+
width: 1.,
377+
color: egui::Color32::WHITE,
378+
},
379+
);
380+
}
381+
382+
Some(Input::FeatureDrag(_, _))
383+
| Some(Input::ConstraintDrag(_, _))
384+
| Some(Input::EditingLineLength(_))
385+
| None => {}
386+
};
327387

328388
self.tools.paint(ui, painter, response, hp, &base_params);
329389

390+
// if let Some(Input::EditingLineLength(ck)) = current_input {
391+
// if let Some(Constraint::LineLength(_, fk, _, dd)) = self.drawing.constraints.get(ck) {
392+
// if let Some(Feature::LineSegment(_, f1, f2)) = self.drawing.features.get(*fk) {
393+
// let (a, b) = match (
394+
// self.drawing.features.get(*f1).unwrap(),
395+
// self.drawing.features.get(*f2).unwrap(),
396+
// ) {
397+
// (Feature::Point(_, x1, y1), Feature::Point(_, x2, y2)) => {
398+
// (egui::Pos2 { x: *x1, y: *y1 }, egui::Pos2 { x: *x2, y: *y2 })
399+
// }
400+
// _ => panic!("unexpected subkey types: {:?} & {:?}", f1, f2),
401+
// };
402+
403+
// let reference = egui::Vec2::from((dd.x, dd.y));
404+
// let t = (a - b).angle() + reference.angle();
405+
// let reference_screen = self.drawing.vp.translate_point(a.lerp(b, 0.5))
406+
// + egui::Vec2::angled(t) * reference.length();
407+
408+
// let area_response = egui::Area::new(popup_id)
409+
// .order(egui::Order::Foreground)
410+
// .fixed_pos(reference_screen)
411+
// .constrain(true)
412+
// .pivot(egui::Align2::CENTER_CENTER)
413+
// .show(ui.ctx(), |ui| {
414+
// ui.vertical(|ui| ui.label("HI"));
415+
// // egui::Frame::popup(ui.style()).show(ui, |ui| {
416+
// // ui.label("HI");
417+
// // });
418+
// })
419+
// .response;
420+
// };
421+
// };
422+
// }
423+
330424
self.draw_debug(ui, painter, hp, &base_params);
331425
}
332426

0 commit comments

Comments
 (0)