////////////////////////////////////////////////////////////////////////////////
// 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 "colormenu.hpp"
#include "../level.hpp"
#include "utils/geometry.hpp"
namespace graphcoloring {
int ColorMenu::number_of_color_menus = 0;
ColorMenu::ColorMenu(gui::Window* window_, int x_, int y_,
const gui::Position& viewport_position_,
std::function color_click_callback_)
: window(window_), x(x_), y(y_), viewport_position(viewport_position_),
color_click_callback(color_click_callback_)
{
number_of_color_menus++;
if (number_of_color_menus == 1)
{
MakeButtons();
callback_id = window->SetMousedownCallback([this](gui::Window*,int x,int y){
if (!IsInsideMenu(x,y) && close_callback)
close_callback();
});
}
else
{
callback_id = -1;
}
}
ColorMenu::~ColorMenu()
{
if (callback_id != -1)
window->RemoveMousedownCallback(callback_id);
number_of_color_menus--;
}
void ColorMenu::SetCloseCallback(std::function close_callback_)
{
close_callback = close_callback_;
}
int ColorMenu::GetWidth() const
{
int number_of_colors = Level::colors.size();
return SPACING + (SPACING + 2 * CIRCLE_RADIUS) * number_of_colors;
}
int ColorMenu::GetHeight() const
{
return 2 * (CIRCLE_RADIUS + SPACING);
}
void ColorMenu::MakeButtons()
{
int xpos = x + SPACING;
for (gui::Color color : Level::colors)
{
gui::Position pos(xpos, y + SPACING, 0, 0, nullptr,
&negative_viewport_position);
gui::Size size(CIRCLE_RADIUS);
std::unique_ptr button(
new gui::Button(window, "", pos, size,
color, gui::Alignment::LEFT, gui::Alignment::TOP,
gui::Button::Shape::CIRCLE));
button->SetCommand([this,color] (){
if (!color_click_callback) return;
color_click_callback(color);
}, GDK_BUTTON_PRIMARY);
buttons.push_back(std::move(button));
xpos += SPACING + 2 * CIRCLE_RADIUS;
}
}
void ColorMenu::Render()
{
if (callback_id == -1) // Failed to create ColorMenu
{
close_callback();
return;
}
int view_x = viewport_position.x;
int view_y = viewport_position.y;
negative_viewport_position.SetPos(-view_x, -view_y);
window->SetDrawColor(BACKGROUND_COLOR);
window->DrawRectangle(x-view_x, y-view_y, GetWidth(), GetHeight(), true);
for (std::unique_ptr& button : buttons)
button->Render();
}
bool ColorMenu::IsInsideMenu(int mx, int my) const
{
return utils::geometry::InRectangle(mx, my,
x-viewport_position.X(), y-viewport_position.Y(),
GetWidth(), GetHeight());
}
} // namespace graphcoloring