//////////////////////////////////////////////////////////////////////////////// // 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 . //////////////////////////////////////////////////////////////////////////////// #include "button.hpp" #include #include "utils/geometry.hpp" namespace gui { const std::vector 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 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(); 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