- Refactored edition actions into a separate namespace for reusability

- Direct consequence of the previous : smooth addition of the Edit Menu
This commit is contained in:
Stepland 2019-03-28 10:54:50 +01:00
parent 713bb70c91
commit bba736da08
6 changed files with 201 additions and 108 deletions

View File

@ -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})

96
EditActions.cpp Normal file
View File

@ -0,0 +1,96 @@
//
// Created by Syméon on 28/03/2019.
//
#include "EditActions.h"
void EditActions::undo(std::optional<EditorState>& ed, NotificationsQueue& nq) {
if (ed and ed->chart) {
auto previous = ed->chart->history.get_previous();
if (previous) {
nq.push(std::make_shared<UndoNotification>(**previous));
(*previous)->undoAction(*ed);
ed->densityGraph.should_recompute = true;
}
}
}
void EditActions::redo(std::optional<EditorState>& ed, NotificationsQueue& nq) {
if (ed and ed->chart) {
auto next = ed->chart->history.get_next();
if (next) {
nq.push(std::make_shared<RedoNotification>(**next));
(*next)->doAction(*ed);
ed->densityGraph.should_recompute = true;
}
}
}
void EditActions::cut(std::optional<EditorState>& 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<TextNotification>(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<ToggledNotes>(ed->chart->selectedNotes,false));
ed->chart->selectedNotes.clear();
}
}
void EditActions::copy(std::optional<EditorState>& 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<TextNotification>(ss.str()));
ed->chart->notesClipboard.copy(ed->chart->selectedNotes);
}
}
void EditActions::paste(std::optional<EditorState>& ed, NotificationsQueue& nq) {
if (ed and ed->chart and (not ed->chart->notesClipboard.empty())) {
int tick_offset = static_cast<int>(ed->getCurrentTick());
std::set<Note> 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<TextNotification>(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<ToggledNotes>(ed->chart->selectedNotes,true));
}
}
void EditActions::delete_(std::optional<EditorState>& ed, NotificationsQueue& nq) {
if (ed and ed->chart) {
if (not ed->chart->selectedNotes.empty()) {
ed->chart->history.push(std::make_shared<ToggledNotes>(ed->chart->selectedNotes,false));
nq.push(std::make_shared<TextNotification>("Deleted selected notes"));
for (auto note : ed->chart->selectedNotes) {
ed->chart->ref.Notes.erase(note);
}
ed->chart->selectedNotes.clear();
}
}
}

24
EditActions.h Normal file
View File

@ -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<EditorState>& ed, NotificationsQueue& nq);
void redo(std::optional<EditorState>& ed, NotificationsQueue& nq);
void cut(std::optional<EditorState>& ed, NotificationsQueue& nq);
void copy(std::optional<EditorState>& ed, NotificationsQueue& nq);
void paste(std::optional<EditorState>& ed, NotificationsQueue& nq);
void delete_(std::optional<EditorState>& ed, NotificationsQueue& nq);
};
#endif //FEIS_EDITACTIONS_H

View File

@ -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<EditorState> &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<EditorState>& ed) {
if (ed) {
return ed->saveChangesOrCancel();
} else {
return true;
}
}
/*
* Returns the newly created chart if there is one
*/
std::optional<Chart> ESHelper::NewChartDialog::display(EditorState &editorState) {

View File

@ -107,6 +107,7 @@ public:
void displayLinearView();
saveChangesResponses alertSaveChanges();
bool saveChangesOrCancel();
void updateVisibleNotes();
std::set<Note> visibleNotes;
@ -119,6 +120,8 @@ namespace ESHelper {
void open(std::optional<EditorState>& ed);
void openFromFile(std::optional<EditorState>& ed, std::filesystem::path path);
bool saveOrCancel(std::optional<EditorState>& ed);
class NewChartDialog {
public:

155
main.cpp
View File

@ -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<ToggledNotes>(editorState->chart->selectedNotes,false));
notificationsQueue.push(std::make_shared<TextNotification>("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<TextNotification>(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<int>(editorState->getCurrentTick());
std::set<Note> 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<TextNotification>(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<ToggledNotes>(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<TextNotification>(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<ToggledNotes>(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<RedoNotification>(**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<UndoNotification>(**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())) {