summaryrefslogtreecommitdiff
path: root/src/graphcoloring/graphs/edge.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/graphcoloring/graphs/edge.cpp')
-rw-r--r--src/graphcoloring/graphs/edge.cpp191
1 files changed, 191 insertions, 0 deletions
diff --git a/src/graphcoloring/graphs/edge.cpp b/src/graphcoloring/graphs/edge.cpp
new file mode 100644
index 0000000..91adc1d
--- /dev/null
+++ b/src/graphcoloring/graphs/edge.cpp
@@ -0,0 +1,191 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2018 Leo Tenenbaum
+// This file is part of GraphColoring.
+//
+// GraphColoring is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// GraphColoring is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GraphColoring. If not, see <https://www.gnu.org/licenses/>.
+////////////////////////////////////////////////////////////////////////////////
+
+#include "edge.hpp"
+
+#define _USE_MATH_DEFINES
+#include <cmath>
+#include <cassert>
+
+#include "utils/geometry.hpp"
+#include "utils/errors.hpp"
+
+namespace graphcoloring {
+
+int Edge::id_counter = 0;
+
+void Edge::ResetID()
+{
+ id_counter = 0;
+}
+
+
+Edge::Edge(gui::Window* window_, Vertex& from_, Vertex& to_, gui::Color color_,
+ const gui::Position& viewport_position_, bool directed_)
+ : id(id_counter++), from(from_), to(to_), window(window_),
+ viewport_position(viewport_position_)
+{
+ color = color_;
+ directed = directed_;
+ color_menu = nullptr;
+ mousedown_callback_id =
+ window->SetMousedownCallback([this] (gui::Window*, int x, int y) {
+ MouseCallback(x, y);
+ });
+ x_keyup_callback_id =
+ window->SetKeyupCallback([this] (gui::Window*) {
+ if (hovering && !is_delete_protected && delete_callback
+ && !is_locked)
+ delete_callback();
+ }, GDK_KEY_x);
+}
+
+Edge::~Edge()
+{
+ window->RemoveMousedownCallback(mousedown_callback_id);
+ window->RemoveKeyupCallback(x_keyup_callback_id, GDK_KEY_x);
+}
+
+int Edge::OtherEndpoint(int vertex_id) const
+{
+ if (from.id == vertex_id) return to.id;
+ if (to.id == vertex_id) return from.id;
+ utils::errors::Die("No other endpoint.");
+ return -1;
+}
+
+void Edge::Lock()
+{
+ is_locked = true;
+}
+
+void Edge::Unlock()
+{
+ is_locked = false;
+}
+
+bool Edge::IsHovering() const
+{
+ return hovering;
+}
+
+bool Edge::IsAdjacentTo(const Edge& edge) const
+{
+ return edge.HasEndpoint(from.id) || edge.HasEndpoint(to.id);
+}
+
+void Edge::SetDeleteCallback(std::function<void()> delete_callback_)
+{
+ delete_callback = delete_callback_;
+}
+
+gui::Color Edge::Color() const
+{
+ return color;
+}
+
+bool Edge::ChangeColor(gui::Color new_color)
+{
+ if (is_color_protected) return false;
+ color = new_color;
+ return true;
+}
+
+bool Edge::HasEndpoints(int id1, int id2) const
+{
+ if (from.id == id1 && to.id == id2)
+ return true;
+ return !directed && from.id == id2 && to.id == id1;
+}
+
+bool Edge::HasEndpoint(int v_id) const
+{
+ return from.id == v_id || to.id == v_id;
+}
+
+void Edge::Render(bool is_in_path)
+{
+ int dist = utils::geometry::PointToLineSegmentDistance(
+ window->GetMouseX(), window->GetMouseY(),
+ from.RenderX(), from.RenderY(), to.RenderX(), to.RenderY(),
+ EDGE_CLICK_TOLERANCE);
+ hovering = dist < EDGE_CLICK_TOLERANCE && dist != -1;
+ int from_x = from.RenderX();
+ int from_y = from.RenderY();
+ int to_x = to.RenderX();
+ int to_y = to.RenderY();
+
+ double theta1 = utils::geometry::LineAngle(from_x, from_y, to_x, to_y);
+ double theta2 = utils::geometry::LineAngle(to_x, to_y, from_x, from_y);
+
+ int x1 = from_x + Vertex::VERTEX_RADIUS * std::cos(theta1);
+ int y1 = from_y + Vertex::VERTEX_RADIUS * std::sin(theta1);
+
+ int x2 = to_x + Vertex::VERTEX_RADIUS * std::cos(theta2);
+ int y2 = to_y + Vertex::VERTEX_RADIUS * std::sin(theta2);
+
+ window->SetDrawColor(is_in_path ? gui::colors::WHITE : color);
+ window->DrawLine(x1, y1, x2, y2);
+
+ if (directed)
+ {
+ double theta3 = theta2 - M_PI / 4;
+ double theta4 = theta2 + M_PI / 4;
+
+ int x3 = x2 + ARROW_SIZE * std::cos(theta3);
+ int y3 = y2 + ARROW_SIZE * std::sin(theta3);
+
+ int x4 = x2 + ARROW_SIZE * std::cos(theta4);
+ int y4 = y2 + ARROW_SIZE * std::sin(theta4);
+
+ window->DrawLine(x2, y2, x3, y3);
+ window->DrawLine(x2, y2, x4, y4);
+ }
+
+}
+
+void Edge::RenderColorMenu()
+{
+ if (color_menu != nullptr)
+ color_menu->Render();
+}
+
+
+void Edge::MouseCallback(int mouse_x, int mouse_y)
+{
+ if (!hovering || color_menu != nullptr || is_color_protected
+ || is_locked)
+ return;
+
+ std::function<void(gui::Color)> callback = [this] (gui::Color color) {
+ assert(ChangeColor(color));
+ color_menu = nullptr;
+ };
+
+ color_menu = std::make_unique<ColorMenu>(window,
+ mouse_x+viewport_position.X(), mouse_y+viewport_position.Y(),
+ viewport_position, callback);
+
+ std::function<void()> close_callback = [this] () {
+ color_menu = nullptr;
+ };
+ color_menu->SetCloseCallback(close_callback);
+}
+
+
+} // namespace graphcoloring