summaryrefslogtreecommitdiff
path: root/src/gui/button.cpp
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2018-08-20 20:34:57 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2018-08-20 20:34:57 -0400
commita4460f6d9453bbd7e584937686449cef3e19f052 (patch)
tree037c208f1e20302ed048c0952ef8e3418add9c86 /src/gui/button.cpp
Initial commit0.0.0
Diffstat (limited to 'src/gui/button.cpp')
-rw-r--r--src/gui/button.cpp191
1 files changed, 191 insertions, 0 deletions
diff --git a/src/gui/button.cpp b/src/gui/button.cpp
new file mode 100644
index 0000000..daa224f
--- /dev/null
+++ b/src/gui/button.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 "button.hpp"
+
+#include <iostream>
+
+#include "utils/geometry.hpp"
+
+namespace gui {
+
+const std::vector<guint> Button::MOUSE_BUTTONS = {
+ GDK_BUTTON_PRIMARY, GDK_BUTTON_MIDDLE, GDK_BUTTON_SECONDARY};
+
+Button::Button(Window* window_, const std::string& text_,
+ Position position_, Size size_, Color color_,
+ Position::Alignment horizontal_align_, Position::Alignment vertical_align_,
+ Shape shape_)
+ : window(window_),
+ text(text_),
+ position(position_),
+ size(size_),
+ color(color_),
+ horizontal_align(horizontal_align_),
+ vertical_align(vertical_align_),
+ shape(shape_),
+ hovering(false)
+{
+ // Given a mouse button, this lambda gives the appropriate
+ // mouse_callback_t (which will call CheckClick with the button).
+ std::function<Window::mouse_callback_t(guint)> callback =
+ [this](guint button)->Window::mouse_callback_t {
+ return [this,button](Window*,int,int) {
+ CheckClick(button);
+ };
+ };
+
+
+
+ for (guint button : MOUSE_BUTTONS)
+ {
+ // Initialize callbacks.
+ callbacks[button] = std::vector<callback_t>();
+ int callback_id = window->SetMouseupCallback(callback(button), button);
+ mouseup_callback_ids.push_back(callback_id);
+ }
+}
+
+Button::~Button()
+{
+ int i;
+ for (i = 0; i < (int)MOUSE_BUTTONS.size(); i++)
+ window->RemoveMouseupCallback(mouseup_callback_ids[i],MOUSE_BUTTONS[i]);
+}
+
+
+
+void Button::CheckHovering()
+{
+ int mx = window->GetMouseX(), my = window->GetMouseY();
+ hovering = shape == Shape::RECTANGLE
+ ? utils::geometry::InRectangle(mx, my, GetX(), GetY(),
+ GetWidth(), GetHeight())
+ : utils::geometry::InCircle(mx, my,
+ GetX()+GetRadius(), GetY()+GetRadius(), GetRadius());
+ if (hovering)
+ for (callback_t callback : hover_callbacks)
+ callback();
+}
+
+void Button::CheckClick(guint button)
+{
+ CheckHovering();
+ if (hovering)
+ {
+ for (callback_t callback : callbacks[button])
+ {
+ callback();
+ }
+ }
+}
+
+void Button::Render()
+{
+ CheckHovering();
+ window->SetLineWidth(BORDER_WIDTH);
+ window->SetDrawColor(colors::Shade(color, 0.3));
+ if (shape == Shape::CIRCLE)
+ window->SetTextSize(GetRadius()*CIRCLE_TEXT_SIZE_FACTOR);
+ else
+ window->SetTextSize(GetHeight()*TEXT_SIZE_FACTOR);
+
+ if (hovering)
+ {
+ switch (shape)
+ {
+ case Shape::RECTANGLE:
+ window->DrawRectangle(GetX()+BORDER_WIDTH/2, GetY()+BORDER_WIDTH/2,
+ GetWidth()-BORDER_WIDTH, GetHeight()-BORDER_WIDTH, true);
+ break;
+ case Shape::CIRCLE:
+ window->DrawCircle(GetX()+GetRadius(), GetY()+GetRadius(),
+ GetRadius()-BORDER_WIDTH);
+ break;
+ }
+ }
+
+ window->SetDrawColor(color);
+ switch (shape)
+ {
+ case Shape::RECTANGLE:
+ window->DrawRectangle(GetX(), GetY(), GetWidth(), GetHeight(), false);
+ break;
+ case Shape::CIRCLE:
+ window->DrawCircle(GetX()+GetRadius(), GetY()+GetRadius(), GetRadius(),
+ false);
+ break;
+ }
+
+ int text_x = 0, text_y = 0;
+ switch (shape)
+ {
+ case Shape::RECTANGLE:
+ {
+ Position text_pos(GetX(), GetY(), 0.5, 0.5, &size);
+ text_x = text_pos.X();
+ text_y = text_pos.Y();
+ }
+ break;
+ case Shape::CIRCLE:
+ text_x = GetX() + GetRadius();
+ text_y = GetY() + GetRadius();
+ break;
+ }
+
+ Position text_pos(text_x, text_y);
+ window->DrawText(text, text_pos, Alignment::CENTER, Alignment::CENTER);
+}
+
+void Button::SetCommand(callback_t callback, guint button)
+{
+ callbacks[button].push_back(callback);
+}
+
+void Button::SetHoverCallback(callback_t callback)
+{
+ hover_callbacks.push_back(callback);
+}
+
+int Button::GetWidth() const { return size.X(); }
+int Button::GetHeight() const { return size.Y(); }
+int Button::GetRadius() const { return size.X(); }
+
+int Button::GetX() const
+{
+ return position.AlignedX(horizontal_align, GetWidth());
+}
+
+int Button::GetY() const
+{
+ return position.AlignedY(vertical_align, GetHeight());
+}
+
+void Button::SetPosition(Position position_)
+{
+ position = position_;
+}
+
+void Button::SetAlignment(Alignment horizontal_align_,Alignment vertical_align_)
+{
+ horizontal_align = horizontal_align_;
+ vertical_align = vertical_align_;
+}
+
+
+} // namespace gui