1 /*
2    Copyright (C) 2008 - 2018 by Mark de Wever <koraq@xs4all.nl>
3    Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY.
11 
12    See the COPYING file for more details.
13 */
14 #define GETTEXT_DOMAIN "wesnoth-editor"
15 
16 #include "gui/dialogs/editor/resize_map.hpp"
17 
18 #include "gui/auxiliary/field.hpp"
19 #include "gui/widgets/toggle_button.hpp"
20 #include "gui/widgets/settings.hpp"
21 #include "gui/widgets/slider.hpp"
22 
23 #include "utils/functional.hpp"
24 
25 namespace gui2
26 {
27 namespace dialogs
28 {
29 
30 /*WIKI
31  * @page = GUIWindowDefinitionWML
32  * @order = 2_editor_resize_map
33  *
34  * == Editor resize map ==
35  *
36  * This shows the dialog to resize the current map.
37  *
38  * @begin{table}{dialog_widgets}
39  *
40  * old_width & & label & o &
41  *         Shows the old width of the map. $
42  *
43  * old_height & & label & o &
44  *         Shows the old height of the map. $
45  *
46  * width & & slider & m &
47  *         Determines the new width of the map. $
48  *
49  * height & & slider & m &
50  *         Determines the new height of the map. $
51  *
52  * copy_edge_terrain & & boolean_selector & m &
53  *         Determines whether the border terrains should be used to expand or
54  *         not. $
55  *
56  * expand0 & & toggle_button & m &
57  *         Determines in which direction to expand, shows the north east
58  *         marker. $
59  *
60  * expand1 & & toggle_button & m &
61  *         Determines in which direction to expand, shows the north marker. $
62  *
63  * expand2 & & toggle_button & m &
64  *         Determines in which direction to expand, shows the north west
65  *         marker. $
66  *
67  * expand3 & & toggle_button & m &
68  *         Determines in which direction to expand, shows the east marker. $
69  *
70  * expand4 & & toggle_button & m &
71  *         Determines in which direction to expand, shows the center marker. $
72  *
73  * expand5 & & toggle_button & m &
74  *         Determines in which direction to expand, shows the west marker. $
75  *
76  * expand6 & & toggle_button & m &
77  *         Determines in which direction to expand, shows the south east
78  *         marker. $
79  *
80  * expand7 & & toggle_button & m &
81  *         Determines in which direction to expand, shows the south marker. $
82  *
83  * expand8 & & toggle_button & m &
84  *         Determines in which direction to expand, shows the south west
85  *         marker. $
86  *
87  * @end{table}
88  */
89 
REGISTER_DIALOG(editor_resize_map)90 REGISTER_DIALOG(editor_resize_map)
91 
92 editor_resize_map::editor_resize_map(int& width,
93 									   int& height,
94 									   EXPAND_DIRECTION& expand_direction,
95 									   bool& copy_edge_terrain)
96 	: width_(register_integer("width", true, width))
97 	, height_(register_integer("height", true, height))
98 	, old_width_(width)
99 	, old_height_(height)
100 	, expand_direction_(expand_direction)
101 	, direction_buttons_{}
102 {
103 	register_bool("copy_edge_terrain", false, copy_edge_terrain);
104 
105 	register_label("old_width", false, std::to_string(width));
106 	register_label("old_height", false, std::to_string(height));
107 }
108 
pre_show(window & window)109 void editor_resize_map::pre_show(window& window)
110 {
111 	slider& height = find_widget<slider>(&window, "height", false);
112 	connect_signal_notify_modified(
113 			height,
114 			std::bind(&editor_resize_map::update_expand_direction,
115 						this,
116 						std::ref(window)));
117 
118 	slider& width = find_widget<slider>(&window, "width", false);
119 	connect_signal_notify_modified(
120 			width,
121 			std::bind(&editor_resize_map::update_expand_direction,
122 						this,
123 						std::ref(window)));
124 
125 	std::string name_prefix = "expand";
126 	for(int i = 0; i < 9; ++i) {
127 		std::string name = name_prefix + std::to_string(i);
128 		direction_buttons_[i]
129 				= find_widget<toggle_button>(&window, name, false, true);
130 
131 		connect_signal_notify_modified(*direction_buttons_[i],
132 			std::bind(&editor_resize_map::update_expand_direction, this, std::ref(window)));
133 	}
134 	direction_buttons_[0]->set_value(true);
135 	update_expand_direction(window);
136 }
137 
138 /**
139  * Convert a coordinate on a 3  by 3 grid to an index, return 9 for out of
140  * bounds
141  */
resize_grid_xy_to_idx(const int x,const int y)142 static int resize_grid_xy_to_idx(const int x, const int y)
143 {
144 	if(x < 0 || x > 2 || y < 0 || y > 2) {
145 		return 9;
146 	} else {
147 		return y * 3 + x;
148 	}
149 }
150 
set_direction_icon(int index,std::string icon)151 void editor_resize_map::set_direction_icon(int index, std::string icon)
152 {
153 	if(index < 9) {
154 		direction_buttons_[index]->set_icon_name("icons/arrows/arrows_blank_"
155 												 + icon + "_30.png");
156 	}
157 }
158 
update_expand_direction(window & window)159 void editor_resize_map::update_expand_direction(window& window)
160 {
161 	for(int i = 0; i < 9; ++i) {
162 		if(direction_buttons_[i]->get_value()
163 		   && static_cast<int>(expand_direction_) != i) {
164 
165 			expand_direction_ = static_cast<EXPAND_DIRECTION>(i);
166 			break;
167 		}
168 	}
169 	for(int i = 0; i < static_cast<int>(expand_direction_); ++i) {
170 		direction_buttons_[i]->set_value(false);
171 		set_direction_icon(i, "none");
172 	}
173 	direction_buttons_[expand_direction_]->set_value(true);
174 	for(int i = expand_direction_ + 1; i < 9; ++i) {
175 		direction_buttons_[i]->set_value(false);
176 		set_direction_icon(i, "none");
177 	}
178 
179 	int xdiff = width_->get_widget_value(window) - old_width_;
180 	int ydiff = height_->get_widget_value(window) - old_height_;
181 	int x = static_cast<int>(expand_direction_) % 3;
182 	int y = static_cast<int>(expand_direction_) / 3;
183 	set_direction_icon(expand_direction_, "center");
184 	if(xdiff != 0) {
185 		int left = resize_grid_xy_to_idx(x - 1, y);
186 		int right = resize_grid_xy_to_idx(x + 1, y);
187 		if(xdiff < 0)
188 			std::swap(left, right);
189 		set_direction_icon(left, "left");
190 		set_direction_icon(right, "right");
191 	}
192 	if(ydiff != 0) {
193 		int top = resize_grid_xy_to_idx(x, y - 1);
194 		int bottom = resize_grid_xy_to_idx(x, y + 1);
195 		if(ydiff < 0)
196 			std::swap(top, bottom);
197 		set_direction_icon(top, "up");
198 		set_direction_icon(bottom, "down");
199 	}
200 	if(xdiff < 0 || ydiff < 0 || (xdiff > 0 && ydiff > 0)) {
201 		int nw = resize_grid_xy_to_idx(x - 1, y - 1);
202 		int ne = resize_grid_xy_to_idx(x + 1, y - 1);
203 		int sw = resize_grid_xy_to_idx(x - 1, y + 1);
204 		int se = resize_grid_xy_to_idx(x + 1, y + 1);
205 		if(xdiff < 0 || ydiff < 0) {
206 			std::swap(nw, se);
207 			std::swap(ne, sw);
208 		}
209 		set_direction_icon(nw, "topleft");
210 		set_direction_icon(ne, "topright");
211 		set_direction_icon(sw, "bottomleft");
212 		set_direction_icon(se, "bottomright");
213 	}
214 }
215 
216 } // namespace dialogs
217 } // namespace gui2
218