mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-01-06 11:09:05 +03:00
Spreadsheet: Implement undo functionality where missing
Implement undo/redo functionality in the Spreadsheet application for the "extend" function, the drag-and-drop function, and when copying and pasting.
This commit is contained in:
parent
22575c9370
commit
356eca7e33
Notes:
sideshowbarker
2024-07-17 11:51:12 +09:00
Author: https://github.com/martinfalisse Commit: https://github.com/SerenityOS/serenity/commit/356eca7e33 Pull-request: https://github.com/SerenityOS/serenity/pull/13562 Reviewed-by: https://github.com/alimpfard
@ -292,12 +292,13 @@ Position Sheet::offset_relative_to(Position const& base, Position const& offset,
|
||||
return { new_column, new_row };
|
||||
}
|
||||
|
||||
void Sheet::copy_cells(Vector<Position> from, Vector<Position> to, Optional<Position> resolve_relative_to, CopyOperation copy_operation)
|
||||
Vector<CellChange> Sheet::copy_cells(Vector<Position> from, Vector<Position> to, Optional<Position> resolve_relative_to, CopyOperation copy_operation)
|
||||
{
|
||||
Vector<CellChange> cell_changes;
|
||||
// Disallow misaligned copies.
|
||||
if (to.size() > 1 && from.size() != to.size()) {
|
||||
dbgln("Cannot copy {} cells to {} cells", from.size(), to.size());
|
||||
return;
|
||||
return cell_changes;
|
||||
}
|
||||
|
||||
Vector<Position> target_cells;
|
||||
@ -307,16 +308,20 @@ void Sheet::copy_cells(Vector<Position> from, Vector<Position> to, Optional<Posi
|
||||
auto copy_to = [&](auto& source_position, Position target_position) {
|
||||
auto& target_cell = ensure(target_position);
|
||||
auto* source_cell = at(source_position);
|
||||
auto previous_data = target_cell.data();
|
||||
|
||||
if (!source_cell) {
|
||||
target_cell.set_data("");
|
||||
cell_changes.append(CellChange(target_cell, previous_data));
|
||||
return;
|
||||
}
|
||||
|
||||
target_cell.copy_from(*source_cell);
|
||||
if (copy_operation == CopyOperation::Cut)
|
||||
if (!target_cells.contains_slow(source_position))
|
||||
source_cell->set_data("");
|
||||
cell_changes.append(CellChange(target_cell, previous_data));
|
||||
if (copy_operation == CopyOperation::Cut && !target_cells.contains_slow(source_position)) {
|
||||
cell_changes.append(CellChange(*source_cell, source_cell->data()));
|
||||
source_cell->set_data("");
|
||||
}
|
||||
};
|
||||
|
||||
// Resolve each index as relative to the first index offset from the selection.
|
||||
@ -359,6 +364,8 @@ void Sheet::copy_cells(Vector<Position> from, Vector<Position> to, Optional<Posi
|
||||
dbgln_if(COPY_DEBUG, "Paste from '{}' to '{}'", position.to_url(*this), target.to_url(*this));
|
||||
copy_to(position, resolve_relative_to.has_value() ? offset_relative_to(target, position, resolve_relative_to.value()) : target);
|
||||
}
|
||||
|
||||
return cell_changes;
|
||||
}
|
||||
|
||||
RefPtr<Sheet> Sheet::from_json(JsonObject const& object, Workbook& workbook)
|
||||
|
@ -135,7 +135,7 @@ public:
|
||||
Cut
|
||||
};
|
||||
|
||||
void copy_cells(Vector<Position> from, Vector<Position> to, Optional<Position> resolve_relative_to = {}, CopyOperation copy_operation = CopyOperation::Copy);
|
||||
Vector<CellChange> copy_cells(Vector<Position> from, Vector<Position> to, Optional<Position> resolve_relative_to = {}, CopyOperation copy_operation = CopyOperation::Copy);
|
||||
|
||||
/// Gives the bottom-right corner of the smallest bounding box containing all the written data, optionally limited to the given column.
|
||||
Position written_data_bounds(Optional<size_t> column_index = {}) const;
|
||||
|
@ -30,6 +30,7 @@ public:
|
||||
void update();
|
||||
|
||||
Function<void(Cell&, String&)> on_cell_data_change;
|
||||
Function<void(Vector<CellChange>)> on_cells_data_change;
|
||||
|
||||
private:
|
||||
explicit SheetModel(Sheet& sheet)
|
||||
|
@ -220,6 +220,7 @@ void InfinitelyScrollableTableView::mouseup_event(GUI::MouseEvent& event)
|
||||
Vector<Position> from;
|
||||
Position position { (size_t)m_target_cell.column(), (size_t)m_target_cell.row() };
|
||||
from.append(position);
|
||||
Vector<CellChange> cell_changes;
|
||||
selection().for_each_index([&](auto& index) {
|
||||
if (index == m_starting_selection_index)
|
||||
return;
|
||||
@ -227,8 +228,11 @@ void InfinitelyScrollableTableView::mouseup_event(GUI::MouseEvent& event)
|
||||
Vector<Position> to;
|
||||
Position position { (size_t)index.column(), (size_t)index.row() };
|
||||
to.append(position);
|
||||
sheet.copy_cells(from, to);
|
||||
auto cell_change = sheet.copy_cells(from, to);
|
||||
cell_changes.extend(cell_change);
|
||||
});
|
||||
if (static_cast<SheetModel&>(*this->model()).on_cells_data_change)
|
||||
static_cast<SheetModel&>(*this->model()).on_cells_data_change(cell_changes);
|
||||
update();
|
||||
}
|
||||
|
||||
@ -425,7 +429,9 @@ SpreadsheetView::SpreadsheetView(Sheet& sheet)
|
||||
return;
|
||||
|
||||
auto first_position = source_positions.take_first();
|
||||
m_sheet->copy_cells(move(source_positions), move(target_positions), first_position, Spreadsheet::Sheet::CopyOperation::Cut);
|
||||
auto cell_changes = m_sheet->copy_cells(move(source_positions), move(target_positions), first_position, Spreadsheet::Sheet::CopyOperation::Cut);
|
||||
if (model()->on_cells_data_change)
|
||||
model()->on_cells_data_change(cell_changes);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -193,7 +193,8 @@ SpreadsheetWidget::SpreadsheetWidget(GUI::Window& parent_window, NonnullRefPtrVe
|
||||
return;
|
||||
|
||||
auto first_position = source_positions.take_first();
|
||||
sheet.copy_cells(move(source_positions), move(target_positions), first_position, action == "cut" ? Spreadsheet::Sheet::CopyOperation::Cut : Spreadsheet::Sheet::CopyOperation::Copy);
|
||||
auto cell_changes = sheet.copy_cells(move(source_positions), move(target_positions), first_position, action == "cut" ? Spreadsheet::Sheet::CopyOperation::Cut : Spreadsheet::Sheet::CopyOperation::Copy);
|
||||
undo_stack().push(make<CellsUndoCommand>(cell_changes));
|
||||
} else {
|
||||
for (auto& cell : sheet.selected_cells())
|
||||
sheet.ensure(cell).set_data(StringView { data.data.data(), data.data.size() });
|
||||
@ -284,6 +285,10 @@ void SpreadsheetWidget::setup_tabs(NonnullRefPtrVector<Sheet> new_sheets)
|
||||
undo_stack().push(make<CellsUndoCommand>(cell, previous_data));
|
||||
window()->set_modified(true);
|
||||
};
|
||||
new_view.model()->on_cells_data_change = [&](Vector<CellChange> cell_changes) {
|
||||
undo_stack().push(make<CellsUndoCommand>(cell_changes));
|
||||
window()->set_modified(true);
|
||||
};
|
||||
new_view.on_selection_changed = [&](Vector<Position>&& selection) {
|
||||
auto* sheet_ptr = current_worksheet_if_available();
|
||||
// How did this even happen?
|
||||
|
Loading…
Reference in New Issue
Block a user