diff --git a/CMakeLists.txt b/CMakeLists.txt index abca83f..c43feb4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,7 +50,7 @@ set(SOURCE_FILES SoundEffect.h TimeSelection.h NotesClipboard.cpp - NotesClipboard.h ChartWithHistory.cpp ChartWithHistory.h Preferences.cpp Preferences.h) + NotesClipboard.h ChartWithHistory.cpp ChartWithHistory.h Preferences.cpp Preferences.h EditActions.cpp EditActions.h) #set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${FEIS_SOURCE_DIR}/cmake") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}) diff --git a/EditActions.cpp b/EditActions.cpp new file mode 100644 index 0000000..01425fc --- /dev/null +++ b/EditActions.cpp @@ -0,0 +1,96 @@ +// +// Created by Syméon on 28/03/2019. +// + +#include "EditActions.h" + +void EditActions::undo(std::optional& ed, NotificationsQueue& nq) { + if (ed and ed->chart) { + auto previous = ed->chart->history.get_previous(); + if (previous) { + nq.push(std::make_shared(**previous)); + (*previous)->undoAction(*ed); + ed->densityGraph.should_recompute = true; + } + } +} + +void EditActions::redo(std::optional& ed, NotificationsQueue& nq) { + if (ed and ed->chart) { + auto next = ed->chart->history.get_next(); + if (next) { + nq.push(std::make_shared(**next)); + (*next)->doAction(*ed); + ed->densityGraph.should_recompute = true; + } + } +} + + +void EditActions::cut(std::optional& ed, NotificationsQueue& nq) { + if (ed and ed->chart and (not ed->chart->selectedNotes.empty())) { + + std::stringstream ss; + ss << "Cut " << ed->chart->selectedNotes.size() << " note"; + if (ed->chart->selectedNotes.size() > 1) { + ss << "s"; + } + nq.push(std::make_shared(ss.str())); + + ed->chart->notesClipboard.copy(ed->chart->selectedNotes); + for (auto note : ed->chart->selectedNotes) { + ed->chart->ref.Notes.erase(note); + } + ed->chart->history.push(std::make_shared(ed->chart->selectedNotes,false)); + ed->chart->selectedNotes.clear(); + } +} + +void EditActions::copy(std::optional& ed, NotificationsQueue& nq) { + if (ed and ed->chart and (not ed->chart->selectedNotes.empty())) { + + std::stringstream ss; + ss << "Copied " << ed->chart->selectedNotes.size() << " note"; + if (ed->chart->selectedNotes.size() > 1) { + ss << "s"; + } + nq.push(std::make_shared(ss.str())); + + ed->chart->notesClipboard.copy(ed->chart->selectedNotes); + } +} + +void EditActions::paste(std::optional& ed, NotificationsQueue& nq) { + if (ed and ed->chart and (not ed->chart->notesClipboard.empty())) { + + int tick_offset = static_cast(ed->getCurrentTick()); + std::set pasted_notes = ed->chart->notesClipboard.paste(tick_offset); + + std::stringstream ss; + ss << "Pasted " << pasted_notes.size() << " note"; + if (pasted_notes.size() > 1) { + ss << "s"; + } + nq.push(std::make_shared(ss.str())); + + for (auto note : pasted_notes) { + ed->chart->ref.Notes.insert(note); + } + ed->chart->selectedNotes = pasted_notes; + ed->chart->history.push(std::make_shared(ed->chart->selectedNotes,true)); + } + +} + +void EditActions::delete_(std::optional& ed, NotificationsQueue& nq) { + if (ed and ed->chart) { + if (not ed->chart->selectedNotes.empty()) { + ed->chart->history.push(std::make_shared(ed->chart->selectedNotes,false)); + nq.push(std::make_shared("Deleted selected notes")); + for (auto note : ed->chart->selectedNotes) { + ed->chart->ref.Notes.erase(note); + } + ed->chart->selectedNotes.clear(); + } + } +} \ No newline at end of file diff --git a/EditActions.h b/EditActions.h new file mode 100644 index 0000000..929b050 --- /dev/null +++ b/EditActions.h @@ -0,0 +1,24 @@ +// +// Created by Syméon on 28/03/2019. +// + +#ifndef FEIS_EDITACTIONS_H +#define FEIS_EDITACTIONS_H + +#include "NotificationsQueue.h" +#include "EditorState.h" + +namespace EditActions { + + void undo(std::optional& ed, NotificationsQueue& nq); + void redo(std::optional& ed, NotificationsQueue& nq); + + void cut(std::optional& ed, NotificationsQueue& nq); + void copy(std::optional& ed, NotificationsQueue& nq); + void paste(std::optional& ed, NotificationsQueue& nq); + void delete_(std::optional& ed, NotificationsQueue& nq); + +}; + + +#endif //FEIS_EDITACTIONS_H diff --git a/EditorState.cpp b/EditorState.cpp index 0e5633a..1da5e3a 100644 --- a/EditorState.cpp +++ b/EditorState.cpp @@ -634,6 +634,21 @@ saveChangesResponses EditorState::alertSaveChanges() { } } +/* + * Saves if asked and returns false if user canceled + */ +bool EditorState::saveChangesOrCancel() { + switch(alertSaveChanges()) { + case saveChangesYes: + ESHelper::save(*this); + case saveChangesNo: + case saveChangesDidNotDisplayDialog: + return true; + case saveChangesCancel: + return false; + } +} + /* * This SCREAAAAMS for optimisation, but in the meantime it works ! */ @@ -737,7 +752,19 @@ void ESHelper::openFromFile(std::optional &ed, std::filesystem::pat } /* - * Returns the newly created chart if there is + * returns true if user saved or if saving wasn't necessary + * returns false if user canceled + */ +bool ESHelper::saveOrCancel(std::optional& ed) { + if (ed) { + return ed->saveChangesOrCancel(); + } else { + return true; + } +} + +/* + * Returns the newly created chart if there is one */ std::optional ESHelper::NewChartDialog::display(EditorState &editorState) { diff --git a/EditorState.h b/EditorState.h index 7374c51..feb4c9f 100644 --- a/EditorState.h +++ b/EditorState.h @@ -107,6 +107,7 @@ public: void displayLinearView(); saveChangesResponses alertSaveChanges(); + bool saveChangesOrCancel(); void updateVisibleNotes(); std::set visibleNotes; @@ -119,6 +120,8 @@ namespace ESHelper { void open(std::optional& ed); void openFromFile(std::optional& ed, std::filesystem::path path); + bool saveOrCancel(std::optional& ed); + class NewChartDialog { public: diff --git a/main.cpp b/main.cpp index b9c987b..5a977d9 100644 --- a/main.cpp +++ b/main.cpp @@ -11,6 +11,7 @@ #include "SoundEffect.h" #include "TimeSelection.h" #include "Preferences.h" +#include "EditActions.h" int main(int argc, char** argv) { @@ -65,17 +66,7 @@ int main(int argc, char** argv) { switch (event.type) { case sf::Event::Closed: preferences.save(); - if (editorState) { - switch (editorState->alertSaveChanges()) { - case saveChangesYes: - ESHelper::save(*editorState); - case saveChangesNo: - case saveChangesDidNotDisplayDialog: - window.close(); - case saveChangesCancel: - break; - } - } else { + if (ESHelper::saveOrCancel(editorState)) { window.close(); } break; @@ -168,16 +159,7 @@ int main(int argc, char** argv) { // Delete selected notes from the chart and discard timeSelection case sf::Keyboard::Delete: - if (editorState and editorState->chart) { - if (not editorState->chart->selectedNotes.empty()) { - editorState->chart->history.push(std::make_shared(editorState->chart->selectedNotes,false)); - notificationsQueue.push(std::make_shared("Deleted selected notes")); - for (auto note : editorState->chart->selectedNotes) { - editorState->chart->ref.Notes.erase(note); - } - editorState->chart->selectedNotes.clear(); - } - } + EditActions::delete_(editorState, notificationsQueue); break; /* @@ -310,22 +292,14 @@ int main(int argc, char** argv) { */ case sf::Keyboard::C: if (event.key.control) { - if (editorState and editorState->chart and (not editorState->chart->selectedNotes.empty())) { - - std::stringstream ss; - ss << "Copied " << editorState->chart->selectedNotes.size() << " note"; - if (editorState->chart->selectedNotes.size() > 1) { - ss << "s"; - } - notificationsQueue.push(std::make_shared(ss.str())); - - editorState->chart->notesClipboard.copy(editorState->chart->selectedNotes); - } + EditActions::copy(editorState, notificationsQueue); } break; case sf::Keyboard::O: if (event.key.control) { - ESHelper::open(editorState); + if (ESHelper::saveOrCancel(editorState)) { + ESHelper::open(editorState); + } } break; case sf::Keyboard::P: @@ -341,68 +315,22 @@ int main(int argc, char** argv) { break; case sf::Keyboard::V: if (event.key.control) { - if (editorState and editorState->chart and (not editorState->chart->notesClipboard.empty())) { - - int tick_offset = static_cast(editorState->getCurrentTick()); - std::set pasted_notes = editorState->chart->notesClipboard.paste(tick_offset); - - std::stringstream ss; - ss << "Pasted " << pasted_notes.size() << " note"; - if (pasted_notes.size() > 1) { - ss << "s"; - } - notificationsQueue.push(std::make_shared(ss.str())); - - for (auto note : pasted_notes) { - editorState->chart->ref.Notes.insert(note); - } - editorState->chart->selectedNotes = pasted_notes; - editorState->chart->history.push(std::make_shared(editorState->chart->selectedNotes,true)); - } + EditActions::paste(editorState, notificationsQueue); } break; case sf::Keyboard::X: if (event.key.control) { - if (editorState and editorState->chart and (not editorState->chart->selectedNotes.empty())) { - - std::stringstream ss; - ss << "Cut " << editorState->chart->selectedNotes.size() << " note"; - if (editorState->chart->selectedNotes.size() > 1) { - ss << "s"; - } - notificationsQueue.push(std::make_shared(ss.str())); - - editorState->chart->notesClipboard.copy(editorState->chart->selectedNotes); - for (auto note : editorState->chart->selectedNotes) { - editorState->chart->ref.Notes.erase(note); - } - editorState->chart->history.push(std::make_shared(editorState->chart->selectedNotes,false)); - editorState->chart->selectedNotes.clear(); - } + EditActions::cut(editorState, notificationsQueue); } break; case sf::Keyboard::Y: if (event.key.control) { - if (editorState and editorState->chart) { - auto next = editorState->chart->history.get_next(); - if (next) { - notificationsQueue.push(std::make_shared(**next)); - (*next)->doAction(*editorState); - editorState->densityGraph.should_recompute = true; - } - } + EditActions::redo(editorState, notificationsQueue); } break; case sf::Keyboard::Z: if (event.key.control) { - if (editorState and editorState->chart) { - auto previous = editorState->chart->history.get_previous(); - if (previous) { - notificationsQueue.push(std::make_shared(**previous)); - (*previous)->undoAction(*editorState); - editorState->densityGraph.should_recompute = true; - } - } + EditActions::undo(editorState, notificationsQueue); } break; default: @@ -556,39 +484,33 @@ int main(int argc, char** argv) { { if (ImGui::BeginMenu("File")) { if (ImGui::MenuItem("New")) { - const char* _filepath = tinyfd_saveFileDialog("New File",nullptr,0,nullptr,nullptr); - if (_filepath != nullptr) { - std::filesystem::path filepath(_filepath); - try { - Fumen f(filepath); - f.autoSaveAsMemon(); - editorState.emplace(f); - Toolbox::pushNewRecentFile(std::filesystem::canonical(editorState->fumen.path)); - } catch (const std::exception& e) { - tinyfd_messageBox("Error",e.what(),"ok","error",1); + if (ESHelper::saveOrCancel(editorState)) { + const char* _filepath = tinyfd_saveFileDialog("New File",nullptr,0,nullptr,nullptr); + if (_filepath != nullptr) { + std::filesystem::path filepath(_filepath); + try { + Fumen f(filepath); + f.autoSaveAsMemon(); + editorState.emplace(f); + Toolbox::pushNewRecentFile(std::filesystem::canonical(editorState->fumen.path)); + } catch (const std::exception& e) { + tinyfd_messageBox("Error",e.what(),"ok","error",1); + } } } } ImGui::Separator(); if (ImGui::MenuItem("Open","Ctrl+O")) { - ESHelper::open(editorState); + if (ESHelper::saveOrCancel(editorState)) { + ESHelper::open(editorState); + } } if (ImGui::BeginMenu("Recent Files")) { int i = 0; for (const auto& file : Toolbox::getRecentFiles()) { ImGui::PushID(i); if (ImGui::MenuItem(file.c_str())) { - if (editorState) { - switch(editorState->alertSaveChanges()) { - case saveChangesYes: - ESHelper::save(*editorState); - case saveChangesNo: - case saveChangesDidNotDisplayDialog: - ESHelper::openFromFile(editorState,file); - case saveChangesCancel: - break; - } - } else { + if (ESHelper::saveOrCancel(editorState)) { ESHelper::openFromFile(editorState,file); } } @@ -598,7 +520,9 @@ int main(int argc, char** argv) { ImGui::EndMenu(); } if (ImGui::MenuItem("Close","",false,editorState.has_value())) { - editorState.reset(); + if (ESHelper::saveOrCancel(editorState)) { + editorState.reset(); + } } ImGui::Separator(); if (ImGui::MenuItem("Save","Ctrl+S",false,editorState.has_value())) { @@ -623,6 +547,25 @@ int main(int argc, char** argv) { ImGui::EndMenu(); } if (ImGui::BeginMenu("Edit")) { + if (ImGui::MenuItem("Undo", "Ctrl+Z")) { + EditActions::undo(editorState, notificationsQueue); + } + if (ImGui::MenuItem("Redo", "Ctrl+Y")) { + EditActions::redo(editorState, notificationsQueue); + } + ImGui::Separator(); + if (ImGui::MenuItem("Cut", "Ctrl+X")) { + EditActions::cut(editorState, notificationsQueue); + } + if (ImGui::MenuItem("Copy", "Ctrl+C")) { + EditActions::copy(editorState, notificationsQueue); + } + if (ImGui::MenuItem("Paste", "Ctrl+V")) { + EditActions::paste(editorState, notificationsQueue); + } + if (ImGui::MenuItem("Delete", "Delete")) { + EditActions::delete_(editorState, notificationsQueue); + } ImGui::EndMenu(); } if (ImGui::BeginMenu("Chart",editorState.has_value())) {