From a3eb81cc6b70c03fb40ac4dcd140d5f3ad241ceb Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Tue, 15 Oct 2024 12:17:21 +0200 Subject: move file loading command + try GUI file loading (still broken) --- CMakeLists.txt | 3 +++ Command.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++ Command.h | 32 ++++++++++++++++++++++++++++++ KeyboardCode.h | 11 ++++++++++ LoadFilesCommand.cpp | 45 +++++++++++++++++++++++++++++++++++++++++ LoadFilesCommand.h | 21 ++++++++++++++++++++ MouseCode.h | 7 +++++++ OpenFileGUICommand.cpp | 16 +++++++++++++++ OpenFileGUICommand.h | 10 ++++++++++ Scancode.h | 11 ---------- View.cpp | 46 +++++++++++++++++++++--------------------- View.h | 3 +-- ViewController.cpp | 43 ++++++++++++++++++++++++++++++---------- ViewController.h | 7 +++++-- main.cpp | 39 ++++++------------------------------ 15 files changed, 266 insertions(+), 82 deletions(-) create mode 100644 Command.cpp create mode 100644 Command.h create mode 100644 KeyboardCode.h create mode 100644 LoadFilesCommand.cpp create mode 100644 LoadFilesCommand.h create mode 100644 MouseCode.h create mode 100644 OpenFileGUICommand.cpp create mode 100644 OpenFileGUICommand.h delete mode 100644 Scancode.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 7aa3fd5..bedbdea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,9 @@ add_executable(main Museum.cpp People.cpp Artist.cpp + Command.cpp + OpenFileGUICommand.cpp + LoadFilesCommand.cpp ) target_link_libraries(main diff --git a/Command.cpp b/Command.cpp new file mode 100644 index 0000000..f497f0f --- /dev/null +++ b/Command.cpp @@ -0,0 +1,54 @@ +#include "Command.h" +#include "Exception.h" + +Command::Command(const Command * c) { + this->set_museum(*c->museum); + this->set_view(*c->view); + this->set_controller(*c->controller); +} + +Command::Command(Museum & m, View & v, ViewController & c) { + this->set_museum(m); + this->set_view(v); + this->set_controller(c); +} + +Command::Command(Museum & m, View & v) { + this->set_museum(m); + this->set_view(v); +} + +Command::Command(Museum & m) { + this->set_museum(m); +} + +Museum & Command::get_museum() { + if (this->museum == nullptr) + throw Exception("Command error: command needs museum"); + return *this->museum; +} + +View & Command::get_view() { + if (this->view == nullptr) + throw Exception("Command error: command needs view"); + return *this->view; +} + +ViewController & Command::get_controller() { + if (this->controller == nullptr) + throw Exception("Command error: command needs controller"); + return *this->controller; +} + +void Command::set_museum(Museum & museum) { + this->museum = &museum; +} + +void Command::set_view(View & view) { + this->view = &view; +} + +void Command::set_controller(ViewController & controller) { + this->controller = &controller; +} + diff --git a/Command.h b/Command.h new file mode 100644 index 0000000..bc511ab --- /dev/null +++ b/Command.h @@ -0,0 +1,32 @@ +#pragma once + +class Museum; +class View; +class ViewController; + +class Command { +public: + virtual void execute() = 0; + +public: + Command(const Command * c); + Command(Museum & m, View & v, ViewController & c); + Command(Museum & m, View & v); + Command(Museum & m); + +protected: + Museum & get_museum(); + View & get_view(); + ViewController & get_controller(); + +protected: + void set_museum(Museum &); + void set_view(View &); + void set_controller(ViewController &); + +private: + Museum * museum = nullptr; + View * view = nullptr; + ViewController * controller = nullptr; +}; + diff --git a/KeyboardCode.h b/KeyboardCode.h new file mode 100644 index 0000000..a7232ba --- /dev/null +++ b/KeyboardCode.h @@ -0,0 +1,11 @@ +#pragma once + +typedef enum { + KEY_SPACE = 44, + KEY_ENTER = 40, + KEY_O = 18, + KEY_A = 4, + KEY_LEFT = 80, + KEY_RIGHT = 79, +} KeyboardCode; + diff --git a/LoadFilesCommand.cpp b/LoadFilesCommand.cpp new file mode 100644 index 0000000..05b1311 --- /dev/null +++ b/LoadFilesCommand.cpp @@ -0,0 +1,45 @@ +#include +#include + +#include "LoadFilesCommand.h" +#include "Deserializer.h" +#include "Exception.h" +#include "FileReader.h" +#include "FileStrategy.h" +#include "Museum.h" +#include "Parser.h" + +using namespace std; + +void LoadFilesCommand::execute(int argc, char ** argv) { + vector files = {}; + for (size_t i = 0; i < argc; i++) { + files.push_back(string(argv[i])); + } + return this->execute(files); +} + +void LoadFilesCommand::execute(vector files) { + try { + this->load_files(files); + } catch (Exception & e) { + throw Exception("LoadFilesCommand error: %s", e.what()); + } +} + +void LoadFilesCommand::load_files(vector files) { + this->get_museum().set_pause(true); + + Deserializer deserializer { this->get_museum() }; + for (string url : files) { + unique_ptr file = FileReader::open(url); + try { + Parser::parse(*file, deserializer); + } catch (Exception & e) { + throw Exception("parser error: %s (%s)", e.what(), url.c_str()); + } + } + + this->get_museum().set_pause(false); +} + diff --git a/LoadFilesCommand.h b/LoadFilesCommand.h new file mode 100644 index 0000000..468bb33 --- /dev/null +++ b/LoadFilesCommand.h @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +#include "Command.h" + +class LoadFilesCommand : public Command { +public: + virtual void execute(std::vector files); + virtual void execute(int argc, char ** argv); + +private: + void load_files(std::vector files); + +private: + virtual void execute() {}; // unused + + using Command::Command; +}; + diff --git a/MouseCode.h b/MouseCode.h new file mode 100644 index 0000000..54e7d5a --- /dev/null +++ b/MouseCode.h @@ -0,0 +1,7 @@ +#pragma once + +typedef enum { + MOUSE_LEFT = 1, + MOUSE_RIGHT = 3, +} MouseCode; + diff --git a/OpenFileGUICommand.cpp b/OpenFileGUICommand.cpp new file mode 100644 index 0000000..4568f61 --- /dev/null +++ b/OpenFileGUICommand.cpp @@ -0,0 +1,16 @@ +#include +#include + +#include "OpenFileGUICommand.h" +#include "LoadFilesCommand.h" +#include "View.h" + +using namespace std; + +void OpenFileGUICommand::execute() { + this->get_view().dialog_file([](vector files, void * data) -> void { + auto self = static_cast(data); + LoadFilesCommand(self).execute(files); + }, this); +} + diff --git a/OpenFileGUICommand.h b/OpenFileGUICommand.h new file mode 100644 index 0000000..dfaace3 --- /dev/null +++ b/OpenFileGUICommand.h @@ -0,0 +1,10 @@ +#pragma once + +#include "Command.h" + +class OpenFileGUICommand : public Command { +public: + using Command::Command; + virtual void execute(); +}; + diff --git a/Scancode.h b/Scancode.h deleted file mode 100644 index d838bf2..0000000 --- a/Scancode.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -typedef enum { - KEY_SPACE = 44, - KEY_ENTER = 40, - KEY_O = 18, - KEY_A = 4, - KEY_LEFT = 80, - KEY_RIGHT = 79, -} Scancode; - diff --git a/View.cpp b/View.cpp index c53ad8f..998356f 100644 --- a/View.cpp +++ b/View.cpp @@ -31,8 +31,14 @@ void View::work() { continue; } if (e.type == SDL_EVENT_KEY_DOWN) { - this->ev_keydown(e.key); - continue; + if (e.key.repeat) continue; + this->controller.ev_keydown(static_cast(e.key.scancode)); + } + if (e.type == SDL_EVENT_MOUSE_BUTTON_DOWN) { + this->controller.ev_mousedown(static_cast(e.button.button)); + } + if (e.type == SDL_EVENT_MOUSE_MOTION) { + this->controller.ev_mousemove(e.motion.x, e.motion.y); } } @@ -44,11 +50,6 @@ void View::work() { this->window_deinit(); } -void View::ev_keydown(SDL_KeyboardEvent ev) { - if (ev.repeat) return; - this->controller.keypress(static_cast(ev.scancode)); -} - void View::window_init() { SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS); this->window = SDL_CreateWindow( @@ -102,22 +103,21 @@ void View::draw_rect(Rectangle r, Color c) { } typedef struct { - bool open; - vector out; -} dialog_file_tmp_data; -vector View::dialog_file() { - dialog_file_tmp_data data = { - .open = true, - .out = {}, - }; - SDL_DialogFileCallback callback = [](void * userdata, const char * const * files, int) -> void { - dialog_file_tmp_data * data = static_cast(userdata); + void (* callback)(std::vector files, void* data); + void * data; +} tmp_data; +void View::dialog_file(void(*callback)(std::vector files, void* data), void* data) { + tmp_data * temp = new tmp_data({ + .callback = callback, + .data = data, + }); + SDL_ShowOpenFileDialog([](void * userdata, const char * const * files, int) -> void { + tmp_data * temp = static_cast(userdata); + vector out = {}; for (; *files != NULL; files++) - data->out.push_back(std::string(*files)); - data->open = false; - }; - SDL_ShowOpenFileDialog(callback, &data, this->window, NULL, 0, NULL, true); - while (data.open); - return data.out; + out.push_back(string(*files)); + (*temp->callback)(out, temp->data); + delete temp; + }, temp, this->window, NULL, 0, NULL, true); } diff --git a/View.h b/View.h index 5c8a2a6..c8b2133 100644 --- a/View.h +++ b/View.h @@ -16,7 +16,7 @@ public: public: virtual void window_size(unsigned int width, unsigned int height); - virtual std::vector dialog_file(); + virtual void dialog_file(void(*callback)(std::vector files, void* data), void* data); virtual void draw_rect(Rectangle r, Color c); private: @@ -24,7 +24,6 @@ private: virtual void draw_end(); virtual void window_init(); virtual void window_deinit(); - virtual void ev_keydown(SDL_KeyboardEvent); public: bool open = true; diff --git a/ViewController.cpp b/ViewController.cpp index c7fa50d..fc08c68 100644 --- a/ViewController.cpp +++ b/ViewController.cpp @@ -1,5 +1,8 @@ #include "ViewController.h" -#include "Scancode.h" +#include "Exception.h" +#include "KeyboardCode.h" +#include "MouseCode.h" +#include "OpenFileGUICommand.h" #include "View.h" #include "Museum.h" @@ -47,30 +50,48 @@ void ViewController::update_artists() { } } -void ViewController::keypress(Scancode scancode) { - switch (scancode) { - KEY_SPACE: { +void ViewController::ev_keydown(KeyboardCode key) { + switch (key) { + case KEY_SPACE: { printf("TODO: toggle museum.pause\n"); + // MuseumPauseCommand().toggle(); break; } - KEY_ENTER: { + case KEY_ENTER: { break; } - KEY_O: { - printf("TODO: open dialog\n"); - this->view.dialog_file(); + case KEY_O: { + try { + OpenFileGUICommand(this->museum, this->view, *this).execute(); + } catch (Exception & e) { + printf("OpenFileGUICommand error: %s\n", e.what()); + } break; } - KEY_A: { + case KEY_A: { break; } - KEY_LEFT: { + case KEY_LEFT: { break; } - KEY_RIGHT: { + case KEY_RIGHT: { break; } default: break; } } +void ViewController::ev_mousedown(MouseCode button) { + printf("mouse %d\n", button); + switch (button) { + case MOUSE_LEFT: { + // MuseumPauseCommand().toggle(); + break; + } + default: break; + } +} + +void ViewController::ev_mousemove(unsigned x, unsigned y) { +} + diff --git a/ViewController.h b/ViewController.h index 9e1e812..0f6b3e0 100644 --- a/ViewController.h +++ b/ViewController.h @@ -1,6 +1,7 @@ #pragma once -#include "Scancode.h" +#include "KeyboardCode.h" +#include "MouseCode.h" class View; class Museum; @@ -11,7 +12,9 @@ public: public: void update(); - void keypress(Scancode scancode); + void ev_keydown(KeyboardCode code); + void ev_mousedown(MouseCode code); + void ev_mousemove(unsigned x, unsigned y); private: void update_size(); diff --git a/main.cpp b/main.cpp index f9ef3c0..94cccfe 100644 --- a/main.cpp +++ b/main.cpp @@ -1,48 +1,21 @@ #include #include "Exception.h" -#include "FileReader.h" +#include "LoadFilesCommand.h" #include "Museum.h" -#include "Deserializer.h" -#include "Parser.h" #include "View.h" -#include "ViewController.h" using namespace std; -static unique_ptr open(const char * url) noexcept { - try { - unique_ptr file = FileReader::open(url); - return file; - } catch (Exception & e) { - printf("file open error: %s\n", e.what()); - exit(EXIT_FAILURE); - } -} - -static void parse(FileStrategy & file, Deserializer & deserializer, const char * url) noexcept { - try { - Parser::parse(file, deserializer); - } catch (Exception & e) { - printf("parser error: %s (%s)\n", e.what(), url); - exit(EXIT_FAILURE); - } -} - int main(int argc, char** argv) { Museum museum {}; View view { museum }; - { // load files provided on command line - Deserializer deserializer { museum }; - museum.set_pause(true); - for (int i = 1; i < argc; i++) { - char * url = argv[i]; - - unique_ptr file = open(url); - parse(*file, deserializer, url); - } - museum.set_pause(false); + try { + LoadFilesCommand(museum).execute(argc - 1, &argv[1]); + } catch (Exception & e) { + printf("%s\n", e.what()); + return EXIT_FAILURE; // invalid files on start cause exit } // Museum and View both create their own worker threads, so the main thread -- cgit v1.2.3