From 1ebc473b7f50f88d1a534833d721b0324b523f4a Mon Sep 17 00:00:00 2001 From: Tyler Hinrichs <86966799+tylernh10@users.noreply.github.com> Date: Sun, 8 Jan 2023 14:23:24 -0500 Subject: [PATCH] complete menu functionality --- README.md | 4 ++- header-files/ECGraphicViewImp.h | 7 +++- header-files/ECRealObserver.h | 28 +++++++++++++++ header-files/ShapesModel.h | 11 +++++- source-files/ECGraphicViewImp.cpp | 5 +++ source-files/ECRealObserver.cpp | 37 +++++++++++++++++++- source-files/ShapesModel.cpp | 11 ++++++ source-files/test-gv.cpp | 26 +++++++------- test-files/test.txt | 2 ++ test-files/test1.txt | 57 ++++++++++++++++--------------- test-files/test10.txt | 1 + 11 files changed, 145 insertions(+), 44 deletions(-) create mode 100644 test-files/test.txt create mode 100644 test-files/test10.txt diff --git a/README.md b/README.md index 55f7d31..b2e6f3d 100644 --- a/README.md +++ b/README.md @@ -56,10 +56,12 @@ at a later time. The file will be created if it does not exist. ### Future Features: * Documentation on shape scheme * Makefile for easier compilation -* Menu onscreen allowing users to change colors of shapes, changes modes, etc. +* Menu onscreen allowing users to change colors of shapes, changes modes, etc. *(in progress)* * Add support for users to add onscreen text * Allowing users to specify which file to open in the application instead of only via command line * Detailed documentation on design patterns used * Detailed description on how to install Allegro +### Copyright Info + © Tyler Hinrichs 2022 \ No newline at end of file diff --git a/header-files/ECGraphicViewImp.h b/header-files/ECGraphicViewImp.h index 739b81f..05bdd9d 100644 --- a/header-files/ECGraphicViewImp.h +++ b/header-files/ECGraphicViewImp.h @@ -58,7 +58,9 @@ enum ECGVEventType ECGV_EV_KEY_DOWN_F = 25, ECGV_EV_KEY_UP_F = 26, ECGV_EV_KEY_DOWN_CTRL = 27, - ECGV_EV_KEY_UP_CTRL = 28 + ECGV_EV_KEY_UP_CTRL = 28, + ECGV_EV_KEY_DOWN_S = 29, + ECGV_EV_KEY_DOWN_H = 30 }; //*********************************************************** @@ -144,6 +146,9 @@ class ECGraphicViewImp : public ECObserverSubject void insertCursor(); void defaultCursor(); + // Access view + ALLEGRO_DISPLAY* getDisplay() { return display; } + private: // Internal functions // Initialize and reset view diff --git a/header-files/ECRealObserver.h b/header-files/ECRealObserver.h index 281b55d..114f397 100644 --- a/header-files/ECRealObserver.h +++ b/header-files/ECRealObserver.h @@ -139,6 +139,34 @@ class ECColorObserver : public ECObserver Menu& menu; }; +// Save Observer +// Allows user to save via the keyboard or menu +class ECSaveObserver : public ECObserver +{ +public: + ECSaveObserver(ECGraphicViewImp& view, Controller& ctrl, Menu& m) : view(view), ctrl(ctrl), menu(m) {} + virtual ~ECSaveObserver() {} + virtual void Update(); +private: + ECGraphicViewImp& view; + Controller& ctrl; + Menu& menu; +}; + +// Help Observer +// Allows user to save via the keyboard or menu +class ECHelpObserver : public ECObserver +{ +public: + ECHelpObserver(ECGraphicViewImp& view, Controller& ctrl, Menu& m) : view(view), ctrl(ctrl), menu(m) {} + virtual ~ECHelpObserver() {} + virtual void Update(); +private: + ECGraphicViewImp& view; + Controller& ctrl; + Menu& menu; +}; + // Arrow Key Observers // When pressed, they move all selected shapes 10 by the direction specified by the key pressed class ECGenericArrowObserver : public ECObserver diff --git a/header-files/ShapesModel.h b/header-files/ShapesModel.h index 341b7fb..2bf081f 100644 --- a/header-files/ShapesModel.h +++ b/header-files/ShapesModel.h @@ -5,13 +5,15 @@ #include "Command.h" #include #include +#include +#include using namespace std; class ECCommandHistory; // necessary forward declaration class ShapesModel { public: - ShapesModel(): color(ECGV_BLACK) {} + ShapesModel(string f): color(ECGV_BLACK), filename(f) {} vector getListShapes() { return listShapes; } void addShape(Shape* x) { listShapes.push_back(x); } void removeShape(Shape* x); @@ -32,10 +34,14 @@ class ShapesModel { ECGVColor getColor(); // retrieves current color void setColor(int x); // sets current color + // saving + void save(); + private: vector listShapes; vector selected; ECGVColor color; + string filename; }; class Controller { @@ -107,6 +113,9 @@ class Controller { // color void setColor(int x); + // save + void save() { model->save(); } + private: ShapesModel* model; // reference to model ECCommandHistory* history; // saves history of all commands so far diff --git a/source-files/ECGraphicViewImp.cpp b/source-files/ECGraphicViewImp.cpp index f34b218..d2015ec 100644 --- a/source-files/ECGraphicViewImp.cpp +++ b/source-files/ECGraphicViewImp.cpp @@ -228,7 +228,12 @@ ECGVEventType ECGraphicViewImp::WaitForEvent() case ALLEGRO_KEY_RCTRL: return ECGV_EV_KEY_DOWN_CTRL; + + case ALLEGRO_KEY_S: + return ECGV_EV_KEY_DOWN_S; + case ALLEGRO_KEY_H: + return ECGV_EV_KEY_DOWN_H; } } else if (ev.type == ALLEGRO_EVENT_KEY_UP) { diff --git a/source-files/ECRealObserver.cpp b/source-files/ECRealObserver.cpp index fdf7f90..a38ae62 100644 --- a/source-files/ECRealObserver.cpp +++ b/source-files/ECRealObserver.cpp @@ -1,4 +1,5 @@ #include "../header-files/ECRealObserver.h" +#include // ECModeObserver void ECModeObserver :: Update() { @@ -10,7 +11,7 @@ void ECModeObserver :: Update() { if (ctrl.getMode() == 0) view.defaultCursor(); if (ctrl.getMode() == 1) view.insertCursor(); ctrl.setMouseDownThisMode(0); - ctrl.resetFandGAssertions(); // changes F and G asserted to false when switching modes + //ctrl.resetFandGAssertions(); // changes F and G asserted to false when switching modes view.SetRedraw(true); // needed for color change of selected becoming unselected } } @@ -121,6 +122,40 @@ void ECColorObserver::Update() { } } +void ECSaveObserver::Update() { + if (view.GetCurrEvent() == ECGV_EV_KEY_DOWN_S || + view.GetCurrEvent() == ECGV_EV_MOUSE_BUTTON_DOWN && menu.checkOverButton(18)) { + ctrl.save(); + } +} + +void ECHelpObserver::Update() { + if (view.GetCurrEvent() == ECGV_EV_KEY_DOWN_H || + view.GetCurrEvent() == ECGV_EV_MOUSE_BUTTON_DOWN && menu.checkOverButton(19)) { + al_show_native_message_box(view.getDisplay(), "Help", "Graphical Editor Help Information", + "Use the mouse to draw, select, and move shapes.\n" + "Hover over a button in the menu at the top of the screen to see what it does.\n\n" + "The keyboard can also be used for menu operations.\n" + "Press the spacebar to switch modes (edit and insert).\n" + "Press S to save.\n" + "Press H to open the Help Dialog (this message).\n" + "Press Z to undo an action.\n" + "Press Y to redo an action.\n\n" + "Insert Mode Only:\n" + "Press F to toggle filled and unfilled shapes.\n" + "Press G to toggle inserting a rectangle and ellipse.\n\n" + "Edit Mode Only:\n" + "Press D to delete a shape.\n" + "Press G to group multiple shapes or ungroup a singular grouped shape.\n" + "Hold down CTRL to select and move multiple shapes.\n" + "Use arrow keys to move shapes (can also use mouse to move).\n\n" + "For more information, please visit github.com/tylernh10/graphical-editor or refer to the README.md for this repository.\n\n" + "Thanks for checking out this project! :)" + , + NULL, ALLEGRO_MESSAGEBOX_QUESTION); + } +} + // ECUpArrowObserver void ECUpArrowObserver::Update() { if (view.GetCurrEvent() == ECGV_EV_KEY_DOWN_UP) { diff --git a/source-files/ShapesModel.cpp b/source-files/ShapesModel.cpp index 82f930a..02877ad 100644 --- a/source-files/ShapesModel.cpp +++ b/source-files/ShapesModel.cpp @@ -225,3 +225,14 @@ ECGVColor ShapesModel::getColor() { void ShapesModel::setColor(int x) { color = parseColor(x); } + +void ShapesModel::save() { + if (filename != "") { + ofstream f(filename, std::ios::trunc); + f << getListShapes().size() << endl; + for (auto i : getListShapes()) { + i->writeShape(f); + } + f.close(); + } +} diff --git a/source-files/test-gv.cpp b/source-files/test-gv.cpp index e0b314e..313da8e 100644 --- a/source-files/test-gv.cpp +++ b/source-files/test-gv.cpp @@ -8,8 +8,6 @@ #include "../header-files/Shape.h" #include "../header-files/Menu.h" #include -#include -#include using namespace std; CompositeShape* parseComposite(int numMembers, ifstream& f, ShapesModel* model) { @@ -40,9 +38,12 @@ int real_main(int argc, char** argv) // Initialize view const int widthWin = 1000, heightWin = 1000; ECGraphicViewImp view(widthWin, heightWin); + + // Get filename from command line args + string filename = (argc == 2) ? argv[1] : ""; // Initialize Model and Controller - ShapesModel* model = new ShapesModel; + ShapesModel* model = new ShapesModel(filename); Controller ctrl(model); // Mouse Functions --> these will be accessed in the menu and in the mouse observers @@ -122,7 +123,8 @@ int real_main(int argc, char** argv) } if (x.size() == 2) { model->loadComposite(parseComposite(x.at(1), f, model)); - } else if (x.size() > 2) { + } + else if (x.size() > 2) { model->parseAtomic(x); } } @@ -139,6 +141,8 @@ int real_main(int argc, char** argv) ECTypeInsertObserver* TypeInsertObserver = new ECTypeInsertObserver(view, ctrl, menu); ECCtrlObserver* CtrlKeyObserver = new ECCtrlObserver(view, ctrl); ECColorObserver* ColorObserver = new ECColorObserver(view, ctrl, menu); + ECSaveObserver* SaveObserver = new ECSaveObserver(view, ctrl, menu); + ECHelpObserver* HelpObserver = new ECHelpObserver(view, ctrl, menu); ECUpArrowObserver* UpKeyObserver = new ECUpArrowObserver(view, ctrl); ECDownArrowObserver* DownKeyObserver = new ECDownArrowObserver(view, ctrl); ECLeftArrowObserver* LeftKeyObserver = new ECLeftArrowObserver(view, ctrl); @@ -159,6 +163,8 @@ int real_main(int argc, char** argv) view.Attach(EditModeMouseObserver); view.Attach(InsertModeMouseObserver); view.Attach(ColorObserver); + view.Attach(SaveObserver); + view.Attach(HelpObserver); view.Attach(UpKeyObserver); view.Attach(DownKeyObserver); view.Attach(LeftKeyObserver); @@ -167,14 +173,8 @@ int real_main(int argc, char** argv) // Run application view.Show(); - if (argc == 2) { - ofstream f(argv[1], std::ios::trunc); - f << model->getListShapes().size() << endl; - for (auto i: model->getListShapes()) { - i->writeShape(f); - } - f.close(); - } + // Save before closing + model->save(); // Deallocate pointers delete ModeObserver; @@ -186,6 +186,8 @@ int real_main(int argc, char** argv) delete TypeInsertObserver; delete CtrlKeyObserver; delete ColorObserver; + delete SaveObserver; + delete HelpObserver; delete UpKeyObserver; delete DownKeyObserver; delete LeftKeyObserver; diff --git a/test-files/test.txt b/test-files/test.txt new file mode 100644 index 0000000..5962bb8 --- /dev/null +++ b/test-files/test.txt @@ -0,0 +1,2 @@ +1 +0 4 179 344 179 592 464 592 464 344 0 diff --git a/test-files/test1.txt b/test-files/test1.txt index 739568d..bf86cb1 100644 --- a/test-files/test1.txt +++ b/test-files/test1.txt @@ -1,34 +1,35 @@ -3 +2 +2 4 361 451 361 449 363 449 363 451 0 +4 2 4 2 4 2 4 3 -2 4 89 215 89 226 160 226 160 215 0 -2 4 89 54 89 226 97 226 97 54 0 -2 4 90 54 90 64 160 64 160 54 0 +2 4 46 352 46 363 117 363 117 352 0 +2 4 46 191 46 363 54 363 54 191 0 +2 4 47 191 47 201 117 201 117 191 0 4 4 -2 4 282 55 282 224 289 224 289 55 0 -2 4 283 129 283 140 362 140 362 129 0 -2 4 285 215 285 224 366 224 366 215 0 -2 4 282 52 282 63 362 63 362 52 0 +2 4 239 192 239 361 246 361 246 192 0 +2 4 240 266 240 277 319 277 319 266 0 +2 4 242 352 242 361 323 361 323 352 0 +2 4 239 189 239 200 319 200 319 189 0 4 5 -2 4 187 52 187 62 255 62 255 52 0 -2 4 247 132 247 224 256 224 256 132 0 -2 4 185 52 185 142 193 142 193 52 0 -2 4 185 132 185 142 256 142 256 132 0 -2 4 189 215 189 224 250 224 250 215 0 +2 4 144 189 144 199 212 199 212 189 0 +2 4 204 269 204 361 213 361 213 269 0 +2 4 142 189 142 279 150 279 150 189 0 +2 4 142 269 142 279 213 279 213 269 0 +2 4 146 352 146 361 207 361 207 352 0 4 14 -2 4 228 408 228 415 298 415 298 408 0 -2 4 68 338 68 345 132 345 132 338 0 -2 4 335 272 335 282 414 282 414 272 0 -2 4 62 273 62 281 136 281 136 273 0 -2 4 336 400 336 413 416 413 416 400 0 -2 4 298 337 298 415 306 415 306 337 0 -2 4 127 273 127 415 137 415 137 273 0 -2 4 225 336 225 343 306 343 306 336 0 -2 4 334 272 334 413 342 413 342 272 0 -2 4 175 272 175 415 185 415 185 272 0 -2 4 225 272 225 281 305 281 305 272 0 -2 4 225 272 225 342 232 342 232 272 0 -2 4 407 273 407 411 416 411 416 273 0 -2 4 66 409 66 416 137 416 137 409 0 -2 4 361 451 361 449 363 449 363 451 0 +2 4 191 519 191 526 261 526 261 519 0 +2 4 31 449 31 456 95 456 95 449 0 +2 4 298 383 298 393 377 393 377 383 0 +2 4 25 384 25 392 99 392 99 384 0 +2 4 299 511 299 524 379 524 379 511 0 +2 4 261 448 261 526 269 526 269 448 0 +2 4 90 384 90 526 100 526 100 384 0 +2 4 188 447 188 454 269 454 269 447 0 +2 4 297 383 297 524 305 524 305 383 0 +2 4 138 383 138 526 148 526 148 383 0 +2 4 188 383 188 392 268 392 268 383 0 +2 4 188 383 188 453 195 453 195 383 0 +2 4 370 384 370 522 379 522 379 384 0 +2 4 29 520 29 527 100 527 100 520 0 diff --git a/test-files/test10.txt b/test-files/test10.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/test-files/test10.txt @@ -0,0 +1 @@ +0