summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Jones <admin@danieljon.es>2020-06-25 20:21:31 +0930
committerDaniel Jones <admin@danieljon.es>2020-06-25 20:21:31 +0930
commite94e0492774134f171cded42f03ebe4e892122b0 (patch)
tree18e18fa06eead723185d6d5cebf1d06a078dfa91
parentc40dfb1f7e12f3d127ff8851dc3c7276840a5b81 (diff)
downloadfoxlogicgates-e94e0492774134f171cded42f03ebe4e892122b0.tar.gz
foxlogicgates-e94e0492774134f171cded42f03ebe4e892122b0.zip
functionality: implement loading xml file saved.
-rw-r--r--Gate.cpp9
-rw-r--r--Gate.h7
-rw-r--r--MainWindow.cpp134
-rw-r--r--MainWindow.h4
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<int> output_gate_ids;
+ printf("new gate with id %d\n", id);
+ std::unique_ptr<Gate> 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;