summaryrefslogtreecommitdiff
path: root/src/graphcoloring/graphs/colormenu.cpp
blob: e466de27b2e46d75a5056b4d1ef20967c7c2b987 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
////////////////////////////////////////////////////////////////////////////////
// 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 "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<void(gui::Color)> 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<void()> 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<gui::Button> 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<gui::Button>& 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