diff options
-rw-r--r-- | CMakeLists.txt | 3 | ||||
-rw-r--r-- | Command.cpp | 54 | ||||
-rw-r--r-- | Command.h | 32 | ||||
-rw-r--r-- | KeyboardCode.h (renamed from Scancode.h) | 2 | ||||
-rw-r--r-- | LoadFilesCommand.cpp | 45 | ||||
-rw-r--r-- | LoadFilesCommand.h | 21 | ||||
-rw-r--r-- | MouseCode.h | 7 | ||||
-rw-r--r-- | OpenFileGUICommand.cpp | 16 | ||||
-rw-r--r-- | OpenFileGUICommand.h | 10 | ||||
-rw-r--r-- | View.cpp | 46 | ||||
-rw-r--r-- | View.h | 3 | ||||
-rw-r--r-- | ViewController.cpp | 43 | ||||
-rw-r--r-- | ViewController.h | 7 | ||||
-rw-r--r-- | main.cpp | 39 |
14 files changed, 256 insertions, 72 deletions
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/Scancode.h b/KeyboardCode.h index d838bf2..a7232ba 100644 --- a/Scancode.h +++ b/KeyboardCode.h @@ -7,5 +7,5 @@ typedef enum { KEY_A = 4, KEY_LEFT = 80, KEY_RIGHT = 79, -} Scancode; +} 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 <vector> +#include <string> + +#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<string> files = {}; + for (size_t i = 0; i < argc; i++) { + files.push_back(string(argv[i])); + } + return this->execute(files); +} + +void LoadFilesCommand::execute(vector<string> files) { + try { + this->load_files(files); + } catch (Exception & e) { + throw Exception("LoadFilesCommand error: %s", e.what()); + } +} + +void LoadFilesCommand::load_files(vector<string> files) { + this->get_museum().set_pause(true); + + Deserializer deserializer { this->get_museum() }; + for (string url : files) { + unique_ptr<FileStrategy> 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 <vector> +#include <string> + +#include "Command.h" + +class LoadFilesCommand : public Command { +public: + virtual void execute(std::vector<std::string> files); + virtual void execute(int argc, char ** argv); + +private: + void load_files(std::vector<std::string> 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 <vector> +#include <string> + +#include "OpenFileGUICommand.h" +#include "LoadFilesCommand.h" +#include "View.h" + +using namespace std; + +void OpenFileGUICommand::execute() { + this->get_view().dialog_file([](vector<string> files, void * data) -> void { + auto self = static_cast<OpenFileGUICommand *>(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(); +}; + @@ -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<KeyboardCode>(e.key.scancode)); + } + if (e.type == SDL_EVENT_MOUSE_BUTTON_DOWN) { + this->controller.ev_mousedown(static_cast<MouseCode>(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<Scancode>(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<string> out; -} dialog_file_tmp_data; -vector<string> 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<dialog_file_tmp_data*>(userdata); + void (* callback)(std::vector<std::string> files, void* data); + void * data; +} tmp_data; +void View::dialog_file(void(*callback)(std::vector<std::string> 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<tmp_data*>(userdata); + vector<string> 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); } @@ -16,7 +16,7 @@ public: public: virtual void window_size(unsigned int width, unsigned int height); - virtual std::vector<std::string> dialog_file(); + virtual void dialog_file(void(*callback)(std::vector<std::string> 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(); @@ -1,48 +1,21 @@ #include <cstdio> #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<FileStrategy> open(const char * url) noexcept { - try { - unique_ptr<FileStrategy> 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<FileStrategy> 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 |