Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions crates/app/src/ui/canvas/board.rs
Original file line number Diff line number Diff line change
Expand Up @@ -618,10 +618,17 @@ fn handle_frame_drag(app: &mut PlotxApp, rect: egui::Rect, ui: &Ui) -> bool {
app.reset_interaction();
if let Some(after) = frame_board_pos(app, drag.frame) {
let action = match drag.frame {
FrameRef::Page(ci) => Action::move_canvas_on_board(ci, drag.before, after),
FrameRef::Sheet(di) => Action::move_sheet_on_board(di, drag.before, after),
FrameRef::Page(ci) => Some(Action::move_canvas_on_board(ci, drag.before, after)),
FrameRef::Sheet(di) => app
.doc
.datasets
.get(di)
.map(plotx_core::state::Dataset::resource_id)
.map(|id| Action::move_sheet_on_board(id, drag.before, after)),
};
app.execute_action(action);
if let Some(action) = action {
app.execute_action(action);
}
}
}

Expand Down
6 changes: 5 additions & 1 deletion crates/app/src/ui/canvas/integrals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,11 @@ fn finish_integral_drag(app: &mut PlotxApp, dataset: usize, xspan: f64) {
.unwrap()
.integrals
.clone();
app.execute_action(Action::set_integrals(dataset, drag.before, after));
app.execute_action(Action::set_integrals(
app.doc.datasets[dataset].resource_id(),
drag.before,
after,
));
}

fn integral_context_menu(
Expand Down
6 changes: 5 additions & 1 deletion crates/app/src/ui/canvas/integrals2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,11 @@ fn finish_integral_2d_drag(
.unwrap()
.integrals
.clone();
app.execute_action(Action::set_integrals_2d(dataset, drag.before, after));
app.execute_action(Action::set_integrals_2d(
app.doc.datasets[dataset].resource_id(),
drag.before,
after,
));
}

fn integral_2d_context_menu(
Expand Down
4 changes: 3 additions & 1 deletion crates/app/src/ui/canvas/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,7 @@ mod tests {
visible: true,
group: None,
kind: CanvasObjectKind::Plot(Box::new(PlotObject {
next_series_id: plotx_core::state::SeriesId::new(1),
binding: plotx_core::state::DataBinding::single(DatasetId::new()),
chart: plotx_core::state::ChartSpec::default(),
stack: plotx_core::state::StackSpec::default(),
Expand Down Expand Up @@ -623,6 +624,7 @@ mod tests {
visible: true,
group: None,
kind: CanvasObjectKind::Plot(Box::new(PlotObject {
next_series_id: plotx_core::state::SeriesId::new(1),
binding: plotx_core::state::DataBinding::single(DatasetId::new()),
chart: plotx_core::state::ChartSpec::default(),
stack: plotx_core::state::StackSpec::default(),
Expand Down Expand Up @@ -734,7 +736,7 @@ mod tests {
app.sync_phase_interaction();
assert_eq!(count(&mut app), 0, "no pivot before the Phase editor opens");

app.session.ui.proc_expanded_step = Some(phase_id);
app.session.ui.proc_expanded_step = Some((app.doc.datasets[0].resource_id(), phase_id));
app.sync_phase_interaction();
assert_eq!(app.session.tool, Tool::ManualPhase);
assert!(
Expand Down
6 changes: 5 additions & 1 deletion crates/app/src/ui/canvas/regions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,5 +250,9 @@ fn finish_region_drag(app: &mut PlotxApp, dataset: usize, xspan: f64) {
.unwrap()
.regions
.clone();
app.execute_action(Action::set_regions(dataset, drag.before, after));
app.execute_action(Action::set_regions(
app.doc.datasets[dataset].resource_id(),
drag.before,
after,
));
}
5 changes: 4 additions & 1 deletion crates/app/src/ui/data_sheet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@ pub(super) fn data_sheet_window(app: &mut PlotxApp, ctx: &egui::Context) {
});
if let Some(delta) = commit {
let typed_diagnostic = delta.typed_diagnostic.clone();
app.execute_action(Action::edit_table(di, delta));
app.execute_action(Action::edit_table(
app.doc.datasets[di].resource_id(),
delta,
));
app.session.status = typed_diagnostic.unwrap_or_else(|| "Edited data table.".to_owned());
}
if let Some(request) = transform
Expand Down
5 changes: 4 additions & 1 deletion crates/app/src/ui/file_dialogs/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ fn mixed_columns_import_as_typed_text_without_being_discarded() {
assert!(delta.typed_diagnostic.is_none());
delta
};
app.execute_action(plotx_core::actions::Action::edit_table(0, delta));
app.execute_action(plotx_core::actions::Action::edit_table(
app.doc.datasets[0].resource_id(),
delta,
));
let edited_fingerprint = app.doc.datasets[0]
.as_table()
.unwrap()
Expand Down
16 changes: 14 additions & 2 deletions crates/app/src/ui/object_inspector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,8 +258,20 @@ fn data_section(app: &mut PlotxApp, ci: usize, object: ObjectId, ui: &mut Ui) {
let label = app.doc.datasets[*di].display_name();
if ui.selectable_label(false, label).clicked() {
let mut b = binding.clone();
b.series
.push(SeriesBinding::new(app.doc.datasets[*di].resource_id()));
let Some(series_id) = app
.doc
.canvases
.get_mut(ci)
.and_then(|canvas| canvas.object_mut(object))
.and_then(|object| object.plot_mut())
.map(|plot| plot.allocate_series_id())
else {
continue;
};
let mut series =
SeriesBinding::new(app.doc.datasets[*di].resource_id());
series.id = series_id;
b.series.push(series);
next_binding = Some(b);
}
}
Expand Down
6 changes: 5 additions & 1 deletion crates/app/src/ui/primary_sidebar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,11 @@ fn apply_browser_event(app: &mut PlotxApp, ui: &Ui, event: Option<BrowserEvent>)
let trimmed = name.trim();
let before = app.doc.datasets[di].name();
let after = (!trimmed.is_empty()).then(|| trimmed.to_owned());
app.execute_action(Action::rename_dataset(di, before, after));
app.execute_action(Action::rename_dataset(
app.doc.datasets[di].resource_id(),
before,
after,
));
app.session.ui.rename = None;
}
Some(BrowserEvent::RenameCancel) => app.session.ui.rename = None,
Expand Down
4 changes: 2 additions & 2 deletions crates/app/src/ui/tools/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ pub(super) fn begin_processing_widget(
) {
if resp.drag_started() {
app.session.ui.processing_edit = Some(PendingProcessingEdit {
dataset: di,
dataset: app.doc.datasets[di].resource_id(),
before,
});
}
Expand All @@ -532,7 +532,7 @@ pub(super) fn commit_processing_widget(
.ui
.processing_edit
.take()
.filter(|edit| edit.dataset == di)
.filter(|edit| edit.dataset == app.doc.datasets[di].resource_id())
.map(|edit| edit.before)
.unwrap_or(fallback_before);
let after = DatasetProcessingState::from_dataset(&app.doc.datasets[di]);
Expand Down
62 changes: 51 additions & 11 deletions crates/app/src/ui/tools/processing/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ mod editors;
use egui::{Button, Ui};
use egui_phosphor::regular as icon;
use plotx_core::actions::DatasetProcessingState;
use plotx_core::state::{Dataset, PhaseAxis, PlotxApp};
use plotx_core::state::{Dataset, DatasetId, PhaseAxis, PlotxApp};
use plotx_processing::{
Apodization, AutoPhaseMethod, AxisPipeline, BaselineMethod, BinParams, NormalizeMethod,
PhaseParams, ProcessingStep, ReferenceParams, SmoothMethod, StepDomain, StepId, StepKind,
Expand Down Expand Up @@ -101,14 +101,17 @@ fn step_list(app: &mut PlotxApp, di: usize, axis: PhaseAxis, ui: &mut Ui) {
return;
};

let Some(owner) = app.doc.datasets.get(di).map(Dataset::resource_id) else {
return;
};
let last = steps.len().saturating_sub(1);
let mut op: Option<(StepId, RowOp)> = None;
for (i, step) in steps.iter().enumerate() {
if matches!(step.kind, StepKind::Fft) {
fft_anchor(ui);
continue;
}
row(app, di, axis, step, i == 0, i == last, ui, &mut op);
row(app, di, owner, axis, step, i == 0, i == last, ui, &mut op);
}
if let Some((id, o)) = op {
apply_row_op(app, di, axis, id, o);
Expand All @@ -132,6 +135,7 @@ fn fft_anchor(ui: &mut Ui) {
fn row(
app: &mut PlotxApp,
di: usize,
owner: DatasetId,
axis: PhaseAxis,
step: &ProcessingStep,
first: bool,
Expand All @@ -140,7 +144,7 @@ fn row(
op: &mut Option<(StepId, RowOp)>,
) {
let id = step.id;
let expanded = app.session.ui.proc_expanded_step == Some(id);
let expanded = app.session.ui.proc_expanded_step == Some((owner, id));
ui.horizontal(|ui| {
ui.weak(icon::DOTS_SIX_VERTICAL);
let mut enabled = step.enabled;
Expand All @@ -152,14 +156,14 @@ fn row(
.selectable_label(expanded, editors::kind_label(&step.kind))
.clicked()
{
app.session.ui.proc_expanded_step = if expanded { None } else { Some(id) };
app.session.ui.proc_expanded_step = if expanded { None } else { Some((owner, id)) };
}
if step.source == StepSource::User {
ui.weak("•");
}
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
ui.menu_button(icon::DOTS_THREE, |ui| {
row_menu(app, id, first, last, op, ui)
row_menu(app, owner, id, first, last, op, ui)
});
ui.weak(editors::kind_summary(&step.kind));
});
Expand All @@ -172,16 +176,18 @@ fn row(
}
}

#[allow(clippy::too_many_arguments)]
fn row_menu(
app: &mut PlotxApp,
owner: DatasetId,
id: StepId,
first: bool,
last: bool,
op: &mut Option<(StepId, RowOp)>,
ui: &mut Ui,
) {
if ui.button("Edit").clicked() {
app.session.ui.proc_expanded_step = Some(id);
app.session.ui.proc_expanded_step = Some((owner, id));
ui.close();
}
if ui.button(format!("{} Duplicate", icon::COPY)).clicked() {
Expand Down Expand Up @@ -409,15 +415,31 @@ fn set_phase_method(
}

fn apply_row_op(app: &mut PlotxApp, di: usize, axis: PhaseAxis, id: StepId, op: RowOp) {
let before = DatasetProcessingState::from_dataset(&app.doc.datasets[di]);
let Some(dataset) = app.doc.datasets.get(di) else {
return;
};
let before = DatasetProcessingState::from_dataset(dataset);
let mut after = before.clone();
let duplicate_id = if matches!(op, RowOp::Duplicate) {
match allocate_step_id(app, di) {
Some(id) => Some(id),
// Only spectral datasets expose processing rows; a stale index or a
// non-spectral dataset is a no-op, not a crash.
None => return,
}
} else {
None
};
if let Some(pipe) = state_pipe(&mut after, axis)
&& let Some(idx) = pipe.steps.iter().position(|s| s.id == id)
{
match op {
RowOp::Duplicate => {
let Some(duplicate_id) = duplicate_id else {
return;
};
let mut clone = pipe.steps[idx].clone();
clone.id = StepId::fresh();
clone.id = duplicate_id;
clone.source = StepSource::User;
pipe.steps.insert(idx + 1, clone);
}
Expand Down Expand Up @@ -445,8 +467,24 @@ fn apply_row_op(app: &mut PlotxApp, di: usize, axis: PhaseAxis, id: StepId, op:
app.commit_processing_edit(di, before, after);
}

/// Reserve a step identity from the dataset that will own it. `None` for a
/// stale index or a dataset kind with no processing pipeline.
fn allocate_step_id(app: &mut PlotxApp, di: usize) -> Option<StepId> {
match app.doc.datasets.get_mut(di)? {
Dataset::Nmr(dataset) => Some(dataset.allocate_step_id()),
Dataset::Nmr2D(dataset) => Some(dataset.allocate_step_id()),
_ => None,
}
}

fn add_step(app: &mut PlotxApp, di: usize, axis: PhaseAxis, kind: StepKind) {
let before = DatasetProcessingState::from_dataset(&app.doc.datasets[di]);
let Some(dataset) = app.doc.datasets.get(di) else {
return;
};
let before = DatasetProcessingState::from_dataset(dataset);
let Some(id) = allocate_step_id(app, di) else {
return;
};
let mut after = before.clone();
if let Some(pipe) = state_pipe(&mut after, axis) {
let fft = pipe
Expand All @@ -458,7 +496,7 @@ fn add_step(app: &mut PlotxApp, di: usize, axis: PhaseAxis, kind: StepKind) {
_ => pipe.steps.len(),
};
pipe.steps
.insert(at, ProcessingStep::new(kind, StepSource::User));
.insert(at, ProcessingStep::new(id, kind, StepSource::User));
}
app.commit_processing_edit(di, before, after);
}
Expand All @@ -470,7 +508,9 @@ fn reset_to_default(app: &mut PlotxApp, di: usize) {
app.session.ui.proc_pending = None;
let before = DatasetProcessingState::from_dataset(&app.doc.datasets[di]);
app.execute_action(plotx_core::actions::Action::update_dataset_processing(
di, before, after,
app.doc.datasets[di].resource_id(),
before,
after,
));
}

Expand Down
12 changes: 10 additions & 2 deletions crates/app/src/ui/tools/pseudo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ pub(super) fn experiment_group(app: &mut PlotxApp, di: usize, ui: &mut Ui) -> bo
*preset = chosen;
params.layout = chosen.layout();
}
app.execute_action(Action::update_dataset_processing(di, before, after));
app.execute_action(Action::update_dataset_processing(
app.doc.datasets[di].resource_id(),
before,
after,
));
}

let is_stack = {
Expand Down Expand Up @@ -279,7 +283,11 @@ fn pseudo_group(app: &mut PlotxApp, di: usize, ui: &mut Ui) {
}
}

let progress = app.session.compute.dosy_progress(di);
let progress = app
.doc
.datasets
.get(di)
.and_then(|dataset| app.session.compute.dosy_progress(dataset.resource_id()));
ui.horizontal(|ui| {
if is_dosy
&& !is_ilt
Expand Down
6 changes: 5 additions & 1 deletion crates/app/src/ui/tools/region_analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,11 @@ fn region_task_body(app: &mut PlotxApp, di: usize, ui: &mut Ui) {
}
if name_lost && let Some(before) = app.session.ui.region_edit_before.take() {
let after = app.doc.datasets[di].as_nmr2d().unwrap().regions.clone();
app.execute_action(Action::set_regions(di, before, after));
app.execute_action(Action::set_regions(
app.doc.datasets[di].resource_id(),
before,
after,
));
}
if let Some((id, m)) = metric_change {
app.edit_regions(di, |regions, _| {
Expand Down
Loading
Loading