From e94e0492774134f171cded42f03ebe4e892122b0 Mon Sep 17 00:00:00 2001 From: Daniel Jones Date: Thu, 25 Jun 2020 20:21:31 +0930 Subject: functionality: implement loading xml file saved. --- Gate.cpp | 9 +++- Gate.h | 7 ++- MainWindow.cpp | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- MainWindow.h | 4 ++ 4 files changed, 147 insertions(+), 7 deletions(-) diff --git a/Gate.cpp b/Gate.cpp index 89a5daa..dab8b7e 100644 --- a/Gate.cpp +++ b/Gate.cpp @@ -17,13 +17,18 @@ int Gate::gate_id_counter = 0; -Gate::Gate(GATE_TYPE type, int x, int y, int width, int height) +Gate::Gate(GATE_TYPE type, int x, int y, int width, int height, int loaded_id) { this->gate_type = type; this->input_gate1 = nullptr; this->input_gate2 = nullptr; //this->output_gate = nullptr; - this->id = Gate::gate_id_counter++; // increment counter after assigning + + /* special handing of id - if the gate is loaded from file the loaded_id will be set and we use that */ + if (loaded_id != -1) + this->id = loaded_id; + else + this->id = Gate::gate_id_counter++; // increment counter after assigning this->x = x; this->y = y; this->w = width; diff --git a/Gate.h b/Gate.h index f271b97..7073aa7 100644 --- a/Gate.h +++ b/Gate.h @@ -36,7 +36,7 @@ class Gate XNOR, }; - Gate(GATE_TYPE type = INPUT, int x = 0, int y = 0, int width = 70, int height = 50); + Gate(GATE_TYPE type = INPUT, int x = 0, int y = 0, int width = 70, int height = 50, int loaded_id = -1); ~Gate(); int get_id() { return this->id; } @@ -62,7 +62,8 @@ class Gate void remove_input_gate(int id); void update_state(); - static int gate_id_counter; // used as the id of a new gate - this is NOT a count of the number of gates + static void set_id_counter(int id) { gate_id_counter = id; }; + static int get_id_counter() { return gate_id_counter; }; private: GATE_TYPE gate_type; @@ -72,6 +73,8 @@ class Gate int w; int h; + static int gate_id_counter; // used as the id of a new gate - this is NOT a count of the number of gates + /* inputs/outputs */ Gate *input_gate1; Gate *input_gate2; diff --git a/MainWindow.cpp b/MainWindow.cpp index 7fa8f03..fe5f5c1 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -39,6 +39,7 @@ FXDEFMAP(MainWindow) MainWindow_Map[]= /* options */ FXMAPFUNC(SEL_COMMAND, MainWindow::ID_BUTTON_SAVE, MainWindow::save_button_press), + FXMAPFUNC(SEL_COMMAND, MainWindow::ID_BUTTON_LOAD, MainWindow::load_button_press), }; FXIMPLEMENT(MainWindow, FXMainWindow, MainWindow_Map, ARRAYNUMBER(MainWindow_Map)) @@ -138,6 +139,8 @@ MainWindow::create_ui() /* save/load */ new FXLabel(optionsFrame, "Save", NULL, JUSTIFY_CENTER_X); new FXButton(optionsFrame, "Save", nullptr, this, MainWindow::ID_BUTTON_SAVE, BUTTON_NORMAL|LAYOUT_FILL_X); + new FXLabel(optionsFrame, "Load", NULL, JUSTIFY_CENTER_X); + new FXButton(optionsFrame, "Load", nullptr, this, MainWindow::ID_BUTTON_LOAD, BUTTON_NORMAL|LAYOUT_FILL_X); } void @@ -493,7 +496,7 @@ MainWindow::save_file() /* write meta data */ auto meta = doc.append_child("Meta"); pugi::xml_node info_xml = meta.append_child("Info"); - info_xml.append_attribute("next_id") = Gate::gate_id_counter; + info_xml.append_attribute("next_id") = Gate::get_id_counter(); auto root = doc.append_child("Gates"); @@ -518,11 +521,12 @@ MainWindow::save_file() /* iterate through all output gates and write them */ for(auto id = gate->get_output_gates()->begin(); id != gate->get_output_gates()->end(); ++id) { - gate_xml.append_attribute("output_gate_id") = (*id); + auto outid_node = gate_xml.append_child("output_gate_id"); + outid_node.append_attribute("id") = (*id); } } - bool saved = doc.save_file(file_name.c_str(), PUGIXML_TEXT(" ")); + bool saved = doc.save_file(file_name.c_str()); if (saved) printf("saved to %s\n", file_name.c_str()); @@ -532,6 +536,123 @@ MainWindow::save_file() return true; } +bool +MainWindow::load_file() +{ + FXString filename=FXFileDialog::getOpenFilename(this, "Open", "", "XML files (*.xml)\nAll Files(*.*)"); + if(!filename.empty()) + { + file_name = filename.text(); + printf("loading from %s\n", file_name.c_str()); + } + else + { + /* cannot load */ + return false; + } + + int next_gate_id = 0; + pugi::xml_document doc; + pugi::xml_parse_result result = doc.load_file(file_name.c_str(), + pugi::parse_default|pugi::parse_declaration); + if (!result) + { + /* failed reading file */ + return false; + } + + remove_all_gates(); + + /* read meta info */ + auto meta_objects = doc.child("Meta"); + next_gate_id = meta_objects.child("Info").attribute("next_id").as_int(); + printf("next gate id after loading is: %d\n", next_gate_id); + + /* read gates */ + auto node_objects = doc.child("Gates"); + for (auto node: node_objects.children("Gate")) + { + int id, x, y, w, h; + bool output_state; + Gate::GATE_TYPE type; + + id = node.attribute("id").as_int(); + x = node.attribute("x").as_int(); + y = node.attribute("y").as_int(); + w = node.attribute("w").as_int(); + h = node.attribute("h").as_int(); + type = (Gate::GATE_TYPE)node.attribute("type").as_int(); + output_state = node.attribute("output_state").as_bool(); + std::vector output_gate_ids; + printf("new gate with id %d\n", id); + std::unique_ptr gate(new Gate(type, x, y, w, h, id)); + gate->set_state(output_state); + + /* read output gate ids */ + for (auto output_node: node.children("output_gate_id")) + { + int out_id = output_node.attribute("id").as_int(); + output_gate_ids.push_back(out_id); + } + + /*set output ids */ + for (auto idout = output_gate_ids.begin(); idout != output_gate_ids.end(); ++idout) + { + gate->add_output_gate_id((*idout)); + } + + gates.push_back(std::move(gate)); + } + + /* iterate again through all gates in the xml file and set output gates if they exist */ + + for (auto node: node_objects.children("Gate")) + { + int input1 = -1; + int input2 = -1; + Gate *gate; + + if (strcmp(node.attribute("input1_id").as_string(), "") != 0) + { + input1 = node.attribute("input1_id").as_int(); + printf("input 1 exists: %d\n", input1); + } + if (strcmp(node.attribute("input2_id").as_string(), "") != 0) + { + input2 = node.attribute("input2_id").as_int(); + printf("input 2 exists: %d\n", input2); + } + + gate = find_gate_by_id(node.attribute("id").as_int()); + + /* set inputs */ + if (input1 != -1) + { + gate->set_input_gate1(find_gate_by_id(input1)); + } + + if (input2 != -1) + { + gate->set_input_gate2(find_gate_by_id(input2)); + } + } + + /* set gate id counter */ + Gate::set_id_counter(next_gate_id); + return true; +} + +void +MainWindow::remove_all_gates() +{ + gates.clear(); + selected_gate = nullptr; + selected_input.gate = nullptr; + selected_input.input = -1; + Gate::set_id_counter(0); + draw(); +} + long MainWindow::on_paint(FXObject*, FXSelector, void *ptr) { @@ -851,3 +972,10 @@ MainWindow::save_button_press(FXObject *sender, FXSelector sel, void *ptr) save_file(); return 1; } + +long +MainWindow::load_button_press(FXObject *sender, FXSelector sel, void *ptr) +{ + load_file(); + return 1; +} diff --git a/MainWindow.h b/MainWindow.h index a27db71..f5de5a1 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -58,6 +58,7 @@ class MainWindow : public FXMainWindow ID_BUTTON_NOT, ID_BUTTON_SAVE, + ID_BUTTON_LOAD, }; /* Event handlers */ @@ -81,6 +82,7 @@ class MainWindow : public FXMainWindow /* options */ long save_button_press(FXObject*,FXSelector,void* ptr); + long load_button_press(FXObject*,FXSelector,void* ptr); /* selected gate */ Gate *selected_gate = nullptr; @@ -98,8 +100,10 @@ class MainWindow : public FXMainWindow void find_selected_input(int x, int y); Gate *find_gate_at(int x, int y); Gate *find_gate_by_id(int id); + void remove_all_gates(); bool save_file(); + bool load_file(); FXHorizontalFrame *contents; FXVerticalFrame *canvasFrame; -- cgit v1.2.3