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  |