1 /*
2 Copyright (C) 2000-2013 The Exult Team
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17 */
18 
19 #ifdef HAVE_CONFIG_H
20 #  include <config.h>
21 #endif
22 
23 #include <SDL_events.h>
24 
25 #include "Yesno_gump.h"
26 #include "gamewin.h"
27 #include "mouse.h"
28 #include "game.h"
29 #include "Gump_button.h"
30 #include "Gump_manager.h"
31 #include "font.h"
32 #include "exult.h"
33 #include "touchui.h"
34 
35 #include <cstring>
36 
37 /*
38  *  Statics:
39  */
40 
41 short Yesno_gump::yesx = 63;
42 short Yesno_gump::yesnoy = 45;
43 short Yesno_gump::nox = 84;
44 
45 
46 /*
47  *  A 'yes' or 'no' button.
48  */
49 
50 class Yesno_button : public Gump_button {
51 	int isyes;          // 1 for 'yes', 0 for 'no'.
52 public:
Yesno_button(Gump * par,int px,int py,int yes)53 	Yesno_button(Gump *par, int px, int py, int yes)
54 		: Gump_button(par, yes ?
55 		              game->get_shape("gumps/yesbtn")
56 		              : game->get_shape("gumps/nobtn"), px, py),
57 		                isyes(yes)
58 	{  }
59 	// What to do when 'clicked':
60 	bool activate(int button = 1) override;
61 };
62 
63 
64 /*
65  *  Handle 'yes' or 'no' button.
66  */
67 
activate(int button)68 bool Yesno_button::activate(
69     int button
70 ) {
71 	if (button != 1) return false;
72 	static_cast<Yesno_gump *>(parent)->set_answer(isyes);
73 	return true;
74 }
75 
76 
77 /*
78  *  Create a yes/no box.
79  */
80 
Yesno_gump(const std::string & txt,const char * font)81 Yesno_gump::Yesno_gump(
82     const std::string &txt, const char *font
83 ) : Modal_gump(nullptr, game->get_shape("gumps/yesnobox")), text(txt), fontname(font), answer(-1) {
84 	set_object_area(TileRect(6, 5, 116, 32));
85 	add_elem(new Yesno_button(this, yesx, yesnoy, 1));
86 	add_elem(new Yesno_button(this, nox, yesnoy, 0));
87 }
88 
89 /*
90  *  Paint on screen.
91  */
92 
paint()93 void Yesno_gump::paint(
94 ) {
95 	// Paint the gump itself.
96 	paint_shape(x, y);
97 	paint_elems();          // Paint buttons.
98 	// Paint text.
99 	fontManager.get_font(fontname)->paint_text_box(gwin->get_win()->get_ib8(), text.c_str(),
100 	        x + object_area.x, y + object_area.y, object_area.w, object_area.h, 2);
101 	if (touchui != nullptr) {
102 		touchui->showButtonControls();
103 	}
104 	gwin->set_painted();
105 }
106 
107 /*
108  *  Handle mouse-down events.
109  */
110 
mouse_down(int mx,int my,int button)111 bool Yesno_gump::mouse_down(
112     int mx, int my, int button      // Position in window.
113 ) {
114 	if (button != 1) return false;
115 	pushed = on_button(mx, my);
116 	if (pushed)
117 		pushed->push(button);       // Show it.
118 	return true;
119 }
120 
121 /*
122  *  Handle mouse-up events.
123  */
124 
mouse_up(int mx,int my,int button)125 bool Yesno_gump::mouse_up(
126     int mx, int my, int button          // Position in window.
127 ) {
128 	if (button != 1) return false;
129 
130 	if (pushed) {       // Pushing a button?
131 		pushed->unpush(button);
132 		if (pushed->on_button(mx, my))
133 			pushed->activate(button);
134 		pushed = nullptr;
135 	}
136 	return true;
137 }
138 
139 /*
140  *  Handle ASCII character typed.
141  */
142 
key_down(int chr)143 void Yesno_gump::key_down(int chr) {
144 	if (chr == 'y' || chr == 'Y' || chr == SDLK_RETURN || chr == SDLK_KP_ENTER)
145 		set_answer(1);
146 	else if (chr == 'n' || chr == 'N' || chr == SDLK_ESCAPE)
147 		set_answer(0);
148 }
149 
150 /*
151  *  Get an answer to a question.
152  *
153  *  Output: 1 if yes, 0 if no or ESC.
154  */
155 
ask(const char * txt,const char * font)156 bool Yesno_gump::ask(
157     const char *txt,            // What to ask.
158     const char *font
159 ) {
160 	Yesno_gump dlg(txt, font);
161 	bool answer;
162 	if (!gumpman->do_modal_gump(&dlg, Mouse::hand))
163 		answer = false;
164 	else
165 		answer = dlg.get_answer();
166 	if (touchui != nullptr && gumpman->gump_mode())
167 		touchui->hideButtonControls();
168 	return answer;
169 }
170 
171 
172 
Countdown_gump(const std::string & txt,int timeout,const char * font)173 Countdown_gump::Countdown_gump(const std::string &txt, int timeout, const char *font) :
174 	Yesno_gump(std::string(), font), text_fmt(txt), timer(timeout) {
175 	answer = false;
176 	start_time = SDL_GetTicks();
177 }
178 
run()179 bool Countdown_gump::run() {
180 	int elapsed = SDL_GetTicks() - start_time;
181 	int remaining = timer * 1000 - elapsed;
182 
183 	if (remaining <= 0)  set_answer(0);
184 
185 	char *new_text = new char[text_fmt.size() + 32];
186 	snprintf(new_text, text_fmt.size() + 31, "%s %i...", text_fmt.c_str(), remaining / 1000);
187 	new_text[text_fmt.size() + 31] = 0;
188 	text = new_text;
189 	delete [] new_text;
190 
191 	return true;
192 }
193 
ask(const char * txt,int timeout,const char * font)194 bool Countdown_gump::ask(const char *txt, int timeout, const char *font) {
195 	Countdown_gump dlg(txt, timeout, font);
196 	bool answer;
197 	if (!gumpman->do_modal_gump(&dlg, Mouse::hand))
198 		answer = false;
199 	else
200 		answer = dlg.get_answer();
201 	if (touchui != nullptr && gumpman->gump_mode())
202 		touchui->hideButtonControls();
203 	return answer;
204 }
205