aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt3
-rw-r--r--Command.cpp54
-rw-r--r--Command.h32
-rw-r--r--KeyboardCode.h (renamed from Scancode.h)2
-rw-r--r--LoadFilesCommand.cpp45
-rw-r--r--LoadFilesCommand.h21
-rw-r--r--MouseCode.h7
-rw-r--r--OpenFileGUICommand.cpp16
-rw-r--r--OpenFileGUICommand.h10
-rw-r--r--View.cpp46
-rw-r--r--View.h3
-rw-r--r--ViewController.cpp43
-rw-r--r--ViewController.h7
-rw-r--r--main.cpp39
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();
+};
+
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<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);
}
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<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();
diff --git a/main.cpp b/main.cpp
index f9ef3c0..94cccfe 100644
--- a/main.cpp
+++ b/main.cpp
@@ -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