GraphC/src/gui/GraphEditor.cpp

180 lines
6.1 KiB
C++

#include "gui.hpp"
#include <algorithm>
#include "GraphEditor.hpp"
namespace GraphC::gui {
void GraphEditor::drawNode(const GraphModel::Node& node){
ImNodes::BeginNode(node.id);
ImNodes::BeginNodeTitleBar();
ImGui::TextUnformatted(node.title.c_str());
ImNodes::EndNodeTitleBar();
for(auto& a_p : node.getAttributes()){
auto&& a = *a_p.value;
switch (a.type){
case GraphModel::Attribute::Type::Input:
ImNodes::BeginInputAttribute(a.id);
ImGui::Text("%s", a.title.c_str());
ImNodes::EndInputAttribute();
break;
case GraphModel::Attribute::Type::Output:
ImNodes::BeginOutputAttribute(a.id);
ImGui::Text("%s", a.title.c_str());
ImGui::Indent(40);
ImNodes::EndOutputAttribute();
break;
case GraphModel::Attribute::Type::Static:
ImNodes::BeginStaticAttribute(a.id);
ImGui::Text("%s", a.title.c_str());
ImNodes::EndStaticAttribute();
break;
default:
throw "Node::draw() invalid type";
break;
}
}
static const char* items[]={
"static","input", "output"
};
static int selected_item_i = 0;
if(ImGui::Button("add attribute"))
ImGui::OpenPopup("new_attribute_popup");
if(ImGui::BeginPopup("new_attribute_popup")){
ImGui::SeparatorText("New attribute properties");
static char buf[256];
ImGui::InputText("label", buf, sizeof(buf));
if(ImGui::Button("select type"))
ImGui::OpenPopup("select_type_popup");
ImGui::SameLine();
ImGui::TextUnformatted(items[selected_item_i]);
if(ImGui::BeginPopup("select_type_popup")){
for (int i = 0; i < IM_ARRAYSIZE(items); i++)
if (ImGui::Selectable(items[i]))
selected_item_i = i;
ImGui::EndPopup();
}
if(ImGui::Button("Create attribute")){
graph.createAttribute(GraphModel::Attribute(
graph.id_gen.getNext(),
const_cast<GraphModel::Node*>(&node),
(GraphModel::Attribute::Type)selected_item_i,
std::string(buf)));
std::cout<<"ATTRIBUTES:\n";
std::cout<<graph.getAttributes().generateGraphVizCode()<<std::endl;
ImGui::CloseCurrentPopup();
buf[0] = 0;
selected_item_i = 0;
}
ImGui::EndPopup();
}
ImNodes::EndNode();
}
GraphModel::Node* GraphEditor::CreateExampleNode(const std::string& node_title){
GraphModel::Node* n = graph.createNode(GraphModel::Node(graph.id_gen.getNext(), node_title));
graph.createAttribute(GraphModel::Attribute(graph.id_gen.getNext(), n, GraphModel::Attribute::Type::Input, "In"));
graph.createAttribute(GraphModel::Attribute(graph.id_gen.getNext(), n, GraphModel::Attribute::Type::Output, "Out"));
graph.createAttribute(GraphModel::Attribute(graph.id_gen.getNext(), n, GraphModel::Attribute::Type::Static, "Static"));
return n;
}
GraphEditor::GraphEditor(const std::string& _title)
: title(_title)
{
// CreateExampleNode("Node A");
// CreateExampleNode("Node B");
// CreateExampleNode("Node C");
// CreateExampleNode("Node D");
std::cout<<"NODES:\n";
std::cout<<graph.getNodes().generateGraphVizCode()<<std::endl;
std::cout<<"ATTRIBUTES:\n";
std::cout<<graph.getAttributes().generateGraphVizCode()<<std::endl;
}
void GraphEditor::show(){
editor_open = true;
}
void GraphEditor::hide(){
editor_open = false;
}
void GraphEditor::draw(){
if(!editor_open)
return;
ImGui::Begin(title.c_str(), &editor_open);
ImGui::SetWindowSizeMin(300,300);
if(ImGui::Button("create node")){
ImGui::OpenPopup("create_node_popup");
}
static char buf[256];
if(ImGui::BeginPopup("create_node_popup")){
ImGui::SeparatorText("New node properties");
ImGui::InputText("label", buf, sizeof(buf));
if(ImGui::Button("create node")){
graph.createNode(GraphModel::Node(graph.id_gen.getNext(), buf));
std::cout<<"NODES:\n";
std::cout<<graph.getNodes().generateGraphVizCode()<<std::endl;
buf[0] = 0;
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
ImNodes::BeginNodeEditor();
// draw nodes
for(auto& n_p : graph.getNodes()){
drawNode(n_p.value);
}
// draw edges
for(auto& p : graph.getEdges()){
ImNodes::Link(p.value.id, p.value.to_attr_id, p.value.from_attr_id);
}
ImNodes::EndNodeEditor();
// handle edge creation
GraphModel::id_t from_attr_id, to_attr_id;
if (ImNodes::IsLinkCreated(&from_attr_id, &to_attr_id))
{
if(!graph.tryCreateEdge(from_attr_id, to_attr_id, nullptr)){
ImGui::End();
throw UsefulException(format("can't create edge from attribute %i to attribute %i", from_attr_id, to_attr_id));
}
std::cout<<"EDGES:\n";
std::cout<<graph.getEdges().generateGraphVizCode()<<std::endl;
}
// handle edge destruction
GraphModel::id_t edge_id;
if (ImNodes::IsLinkDestroyed(&edge_id))
{
if(!graph.tryDeleteEdge(edge_id)){
ImGui::End();
throw UsefulException(format("can't delete edge with id %i", edge_id));
}
std::cout<<"EDGES:\n";
std::cout<<graph.getEdges().generateGraphVizCode()<<std::endl;
}
ImGui::End();
}
}