20130313
[gdash.git] / src / framework / settingsactivity.cpp
blob2940e3da2b03316d260de36be9f36b599efc077f
1 /*
2 * Copyright (c) 2007-2013, Czirkos Zoltan http://code.google.com/p/gdash/
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include "config.h"
19 #include <cstring>
20 #include <glib/gi18n.h>
22 #include "framework/settingsactivity.hpp"
23 #include "framework/commands.hpp"
24 #include "input/gameinputhandler.hpp"
25 #include "cave/helper/colors.hpp"
26 #include "cave/gamerender.hpp"
27 #include "gfx/pixbuffactory.hpp"
28 #include "gfx/cellrenderer.hpp"
29 #include "gfx/screen.hpp"
30 #include "gfx/fontmanager.hpp"
31 #include "misc/logger.hpp"
32 #include "misc/printf.hpp"
33 #include "misc/util.hpp"
34 #include "settings.hpp"
36 #include "framework/thememanager.hpp"
39 class SelectKeyActivity: public Activity {
40 public:
41 SelectKeyActivity(App *app, char const *title, char const *action, int *pkeycode)
42 : Activity(app),
43 title(title), action(action), pkeycode(pkeycode) {
45 virtual void keypress_event(KeyCode keycode, int gfxlib_keycode);
46 virtual void redraw_event();
48 private:
49 std::string title, action;
50 int *pkeycode;
54 void SelectKeyActivity::keypress_event(KeyCode keycode, int gfxlib_keycode) {
55 *pkeycode = gfxlib_keycode;
56 app->enqueue_command(new PopActivityCommand(app));
60 void SelectKeyActivity::redraw_event() {
61 int height=6*app->font_manager->get_line_height();
62 int y1=(app->screen->get_height()-height)/2; /* middle of the screen */
63 int cx=2*app->font_manager->get_font_width_narrow(), cy=y1, cw=app->screen->get_width()-2*cx, ch=height;
65 app->draw_window(cx, cy, cw, ch);
66 app->screen->set_clip_rect(cx, cy, cw, ch);
67 app->set_color(GD_GDASH_WHITE);
68 app->blittext_n(-1, y1+app->font_manager->get_line_height(), title.c_str());
69 app->blittext_n(-1, y1+3*app->font_manager->get_line_height(), action.c_str());
70 app->screen->remove_clip_rect();
72 app->screen->flip();
76 class ThemeSelectedCommand: public Command1Param<std::string> {
77 public:
78 ThemeSelectedCommand(App *app, SettingsActivity *activity)
80 Command1Param<std::string>(app),
81 activity(activity),
82 filename(p1) {
85 private:
86 SettingsActivity *activity;
87 std::string &filename;
88 virtual void execute() {
89 Logger l;
90 if (CellRenderer::is_image_ok_for_theme(*app->pixbuf_factory, filename.c_str())) {
91 /* copy theme to user config directory */
92 std::string new_name = filename_for_new_theme(filename.c_str());
93 install_theme(filename.c_str(), new_name.c_str());
94 activity->load_themes();
95 } else {
96 /* if file is not ok as a theme, error was logged */
99 if (!l.empty()) {
100 app->show_text_and_do_command(_("Cannot install theme!"), l.get_messages_in_one_string());
101 l.clear();
107 void SettingsActivity::load_themes() {
108 load_themes_list(*app->pixbuf_factory, themes, themenum);
112 SettingsActivity::SettingsActivity(App *app, Setting *settings_data)
113 : Activity(app)
115 /* copy the pointer into the member variable */
116 settings = settings_data;
117 for (numsettings = 0; settings[numsettings].name != NULL; ++numsettings)
119 numpages = settings[numsettings-1].page + 1; /* number of pages: take it from the last setting */
121 load_themes();
123 yd = app->font_manager->get_line_height();
124 y1.resize(numpages);
125 for (unsigned page = 0; page < numpages; page++) {
126 int num=0;
127 for (unsigned n = 0; n < numsettings; n++)
128 if (settings[n].page == page)
129 num++;
130 y1[page] = (app->screen->get_height() - num*yd) / 2;
132 current = 1; /* 0th is presumably a page identifier */
133 restart = false;
137 SettingsActivity::~SettingsActivity() {
138 gd_theme = themes[themenum];
139 if (restart)
140 app->request_restart();
144 void SettingsActivity::keypress_event(KeyCode keycode, int gfxlib_keycode) {
145 unsigned page = settings[current].page;
146 switch (keycode) {
147 case App::Up:
148 current = gd_clamp(current-1, 0, numsettings-1);
149 break;
150 case App::Down:
151 current = gd_clamp(current+1, 0, numsettings-1);
152 break;
153 case App::PageUp:
154 if (page > 0)
155 while (settings[current].page==page)
156 current--; /* decrement until previous page is found */
157 break;
158 case App::PageDown:
159 if (page < numpages-1)
160 while (settings[current].page==page)
161 current++; /* increment until previous page is found */
162 break;
164 /* CHANGE SETTINGS */
165 case App::Left: /* key left */
166 switch (settings[current].type) {
167 case TypePage:
168 break;
169 case TypeBoolean:
170 *(bool *)settings[current].var=false;
171 break;
172 case TypePercent:
173 *(int *)settings[current].var=gd_clamp(*(int *)settings[current].var - 5, 0, 100);
174 break;
175 case TypeTheme:
176 themenum=gd_clamp(themenum-1, 0, themes.size()-1);
177 break;
178 case TypeStringv:
179 *(int *)settings[current].var=gd_clamp(*(int *)settings[current].var-1, 0, g_strv_length((char **) settings[current].stringv)-1);
180 break;
181 case TypeKey:
182 break;
184 if (settings[current].restart)
185 restart=true;
186 break;
188 case App::Right: /* key right */
189 switch(settings[current].type) {
190 case TypePage:
191 break;
192 case TypeBoolean:
193 *(bool *)settings[current].var=true;
194 break;
195 case TypePercent:
196 *(int *)settings[current].var=gd_clamp(*(int *)settings[current].var + 5, 0, 100);
197 break;
198 case TypeTheme:
199 themenum=gd_clamp(themenum+1, 0, themes.size()-1);
200 break;
201 case TypeStringv:
202 *(int *)settings[current].var=gd_clamp(*(int *)settings[current].var+1, 0, g_strv_length((char **) settings[current].stringv)-1);
203 break;
204 case TypeKey:
205 break;
207 if (settings[current].restart)
208 restart=true;
209 break;
211 case ' ':
212 case App::Enter:
213 switch (settings[current].type) {
214 case TypePage:
215 break;
216 case TypeBoolean:
217 *(bool *)settings[current].var=!*(bool *)settings[current].var;
218 break;
219 case TypePercent:
220 *(int *)settings[current].var=gd_clamp(*(int *)settings[current].var + 5, 0, 100);
221 break;
222 case TypeTheme:
223 themenum=(themenum+1)%themes.size();
224 break;
225 case TypeStringv:
226 *(int *)settings[current].var=(*(int *)settings[current].var+1)%g_strv_length((char **) settings[current].stringv);
227 break;
228 case TypeKey:
229 // TRANSLATORS: 35 chars max
230 app->enqueue_command(new PushActivityCommand(app, new SelectKeyActivity(app, _("Select key for action"), settings[current].name, (int *) settings[current].var)));
231 break;
233 if (settings[current].restart)
234 restart=true;
235 break;
237 case 't':
238 case 'T':
239 // TRANSLATORS: 40 chars max
240 app->select_file_and_do_command(_("Select Image for Theme"), g_get_home_dir(), "*.bmp;*.png", false, "", new ThemeSelectedCommand(app, this));
241 break;
243 case App::Escape: /* finished options menu */
244 app->enqueue_command(new PopActivityCommand(app));
245 break;
248 if (settings[current].type == TypePage)
249 current++;
250 redraw_event();
254 void SettingsActivity::redraw_event() {
255 app->clear_screen();
256 // TRANSLATORS: 40 chars max
257 app->title_line(CPrintf(_("GDash Options, page %d/%d")) % (settings[current].page+1) % numpages);
258 // TRANSLATORS: 40 chars max. Change means to change the setting
259 app->status_line(_("Crsr: Move Space: change Esc: exit"));
260 app->set_color(GD_GDASH_GRAY1);
261 // TRANSLATORS: 40 chars max
262 app->blittext_n(-1, app->screen->get_height() - 2*app->font_manager->get_line_height(), _("Press T to install a new theme."));
264 /* show settings */
265 unsigned page = settings[current].page;
266 unsigned linenum = 0;
267 for (unsigned n = 0; n < numsettings; n++) {
268 if (settings[n].page == page) {
269 std::string value;
270 switch(settings[n].type) {
271 case TypePage:
272 break;
273 case TypeBoolean:
274 value = *(bool *)settings[n].var? _("yes") : _("no");
275 break;
276 case TypePercent:
277 value = SPrintf("%d%%") % *(int *)settings[n].var;
278 break;
279 case TypeTheme:
280 if (themenum==0)
281 value = _("[Default]");
282 else {
283 char *thm = g_filename_display_basename(themes[themenum].c_str());
284 if (strrchr(thm, '.')) /* remove extension */
285 *strrchr(thm, '.')='\0';
286 value = thm;
287 g_free(thm);
289 break;
290 case TypeStringv:
291 value = settings[n].stringv[*(int *)settings[n].var];
292 break;
293 case TypeKey:
294 value = app->gameinput->get_key_name_from_keycode(*(guint *)settings[n].var);
295 break;
298 int y = y1[page]+linenum*yd;
299 if (settings[n].type != TypePage) {
300 int x = 4*app->font_manager->get_font_width_narrow();
301 app->blittext_n(x, y, CPrintf("%c%s %c%s") % (current==n ? GD_COLOR_INDEX_YELLOW : GD_COLOR_INDEX_LIGHTBLUE) % settings[n].name % GD_COLOR_INDEX_GREEN % value);
302 } else {
303 int x = 2*app->font_manager->get_font_width_narrow();
304 app->blittext_n(x, y, CPrintf("%c%s") % GD_COLOR_INDEX_WHITE % settings[n].name);
306 linenum++;
309 app->screen->flip();