20130313
[gdash.git] / src / framework / app.hpp
blobfa118d114a82291cb76702487317d9fae803502a
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 #ifndef _GD_APP
18 #define _GD_APP
20 #include "config.h"
22 #include <glib.h>
23 #include <stack>
24 #include <queue>
25 #include <string>
27 #include "misc/smartptr.hpp"
28 #include "framework/activity.hpp"
31 class GdColor;
32 class PixbufFactory;
33 class FontManager;
34 class Screen;
35 class Pixmap;
36 class CaveSet;
37 class Command;
38 class GameInputHandler;
39 class App;
40 class Activity;
41 class Screen;
42 class Setting;
43 template <typename T> class Command1Param;
46 std::string help_strings_to_string(char const **strings);
48 /// @ingroup Framework
49 /**
50 * The App object manages Activity objects by organizing them in a stack,
51 * and always sending timer and user events to the topmost one.
53 * The App object is responsible for the activity objects. New activities
54 * are can be pushed into it, thus they become the topmost one. The
55 * activities should be dynamically allocated, and the App will delete
56 * them when they are no longer needed (they are popped from the stack).
58 * The normal use of the App class is creating an App object and pushing
59 * the first activity onto its stack. This first activity is then receiving
60 * the events, and is also allowed to create new activities. All timer,
61 * keyboard and redraw events which are received by the owner of the app
62 * object by some operating system or graphics library dependent way, must
63 * be forwarded to the App using one of its event() methods. The app will
64 * then send it to the topmost activity. The app also generates special
65 * events for the activities when it manages them; for example, when an
66 * activity becomes the topmost one or it is occluded by a new one, it is
67 * notified.
69 * The activities are enabled to create Command objects and enqueue them
70 * in the app. The app will execute these commands after any kind of event.
72 * In order to make an App object work, it must be assigned many helper
73 * objects which do the OS and graphics library abstraction. These objects
74 * are a Screen, a GameInputHandler, a FontManager and a PixbufFactory. The
75 * activities inside the application are allowed - and required - to use
76 * these objects to do their work.
78 * The App object also provides simple drawing methods not implemented anywhere
79 * else, like clearing the screen, setting the color of the next text written,
80 * or drawing a status line.
81 * @todo Move the drawing commands in the App class to the Screen class?
83 * The App object can tell its owner when the last activity exited (and
84 * therefore the app became defunct) or when one of the activities requested
85 * a complete restart of the application. This is implemented using Command
86 * objects, which can be assigned to such events.
88 * The App object provides functions for common tasks like selecting a file
89 * or showing a piece of text. By default, these functions create the corresponding
90 * activity. However, derived classes of the App class are allowed to override
91 * these functions to specialize the user interface: for example, a GTK+
92 * specialization can provide the builtin file selection dialog of GTK+ instead of
93 * the one implemented by the SelectFileActivity class.
95 class App {
96 public:
97 /**
98 * These keycodes are an abstraction to the keycodes provided by the graphics
99 * library. The owner of the App object should translate the pressing of these
100 * keys to the codes, so the Activity objects can work with them, regardless of
101 * the actual graphics library. */
102 enum KeyCodeSpecialKey {
103 Unknown = 0,
104 Up = 1,
105 Down = 2,
106 Left = 3,
107 Right = 4,
108 PageUp = 5,
109 PageDown = 6,
110 Home = 7,
111 End = 8,
112 Tab = 9,
114 F1 = 11,
115 F2 = 12,
116 F3 = 13,
117 F4 = 14,
118 F5 = 15,
119 F6 = 16,
120 F7 = 17,
121 F8 = 18,
122 F9 = 19, ///< reserved for volume
123 F10 = 20, ///< reserved for gtk+ menu
124 F11 = 21, ///< reserved for fullscreen
125 F12 = 22, ///< reserved for fake restart
127 BackSpace = 25,
128 Enter = 26,
129 Escape = 27,
132 /** Constructor.
133 * After construction, the app should also be provided with a PixbufFactory,
134 * a Screen, a GameInputHandler and a FontManager by simple assignment to the
135 * corresponding pointer members. These will be deleted upon the destruction
136 * of the app object. The app object might also be assigned a caveset, in case
137 * the activities in it use it. */
138 App();
139 /** Destructor.
140 * Deletes the screen, the gameinputhandler, the fontmanager and the pixbuffactory. */
141 virtual ~App();
142 /** Set a Command to be executed when the app sees that it finished its work.
143 * This happens when there are no activities in it and also there are no commands
144 * in its queue to execute. */
145 void set_no_activity_command(SmartPtr<Command> command);
146 /** Set the Command which is executed when the App is sent a quit event by calling
147 * its App::quit_event() method. The task of the command object which is to be set
148 * here is to decide what to do when the user closes the application. It might pop
149 * all activities (therefore forcing the App to quit) or it might ask the user if
150 * he wants to save his work. */
151 void set_quit_event_command(SmartPtr<Command> command);
152 /** Set the command to be executed when the App::request_restart() method is called.
153 * Activities can call this method to request their running enviroment to restart,
154 * for example because the sound card settings are changed or because a new
155 * PixbufFactory is to be created. */
156 void set_request_restart_command(SmartPtr<Command> command);
157 /** Set the command to be executed on an App::start_editor() call. */
158 void set_start_editor_command(SmartPtr<Command> command);
160 /* drawing */
161 /** Clear the screen with a nice dark background. */
162 void clear_screen();
163 /** Set the color of the next text drawn. */
164 void set_color(const GdColor &color);
165 /** Draw some text with narrow characters on the screen.
166 * The text may contain color setting characters. */
167 int blittext_n(int x, int y, const char *text);
168 /** Set the title line, which is the topmost line on the screen. */
169 void title_line(const char *text);
170 /** Set the status line, which is the bottom line on the screen. */
171 void status_line(const char *text);
172 /** Draw a black window with a small frame. */
173 void draw_window(int rx, int ry, int rw, int rh);
175 /* customizable ui features */
176 /** Create a file selection dialog, and when the user accepts
177 * the selection, parametrize the command with the name of the file and execute it.
178 * By default, this creates a SelectFileActivity, but derived classes can override it.
179 * @param title The title of the file selection dialog.
180 * @param start_dir The directory in which the file selection should start.
181 * @param glob A semicolon-separated list of file name globs to select the files to show, eg. *.bd;*.gds.
182 * @param for_save If the purpose of the file selection is saving a file.
183 * @param command_when_successful The Command to be executed when the file selection is successful. */
184 virtual void select_file_and_do_command(const char *title, const char *start_dir, const char *glob, bool for_save, const char *defaultname, SmartPtr<Command1Param<std::string> > command_when_successful);
185 /** Ask the user a simple yes or no question, and then execute the corresponding Command.
186 * By default, this creates an AskYesNoActivity, but derived classes can override it.
187 * @param question The text of the question.
188 * @param yes_answer The text of the yes-answer.
189 * @param no_answer The text of the no-answer.
190 * @param command_when_yes The command to be executed if the user said yes. May be NULL.
191 * @param command_when_no The command to be executed if the user said no. May be NULL. */
192 virtual void ask_yesorno_and_do_command(char const *question, const char *yes_answer, char const *no_answer, SmartPtr<Command> command_when_yes, SmartPtr<Command> command_when_no);
193 /** Show a long text to the user. The text may contain line breaks and color setting
194 * codes interpreted by the FontManager::blittext() routine. It is also wrapped to
195 * fit the width of the screen.
196 * By default, this creates a ShowTextActivity, but derived classes can override it.
197 * @param title_line The title of the window.
198 * @param text The text to be shown.
199 * @param command_after_exit The Command to be executed after the activity is closed. May be omitted. */
200 virtual void show_text_and_do_command(char const *title_line, std::string const &text, SmartPtr<Command> command_after_exit = SmartPtr<Command>());
201 /** Show an about dialog with data form the About class.
202 * By default, this creates a ShowTextActivity with the text, but derived classes can override it. */
203 virtual void show_about_info();
204 /** Ask the user to type one line of text, and when successful, call the Command parametrized with the text.
205 * @param title_line The title of the window.
206 * @param default_text The default value of the text box.
207 * @param command_when_successful The command of one string parameter to be parametrized with the line
208 * typed and executed, if the user accepts the input. */
209 virtual void input_text_and_do_command(char const *title_line, char const *default_text, SmartPtr<Command1Param<std::string> > command_when_successful);
210 /** This method is to be called by Activity object to tell the App if a game is running.
211 * By default, it does nothing, however derived classes may override it. */
212 virtual void game_active(bool active) {}
213 /** Show the settings screen for the array of settable parameters.
214 * @param settings Array of settable parameters, delimited with an item with a NULL name. */
215 virtual void show_settings(Setting *settings);
216 /** Show a short message in a small window.
217 * @param primary The message to show - first part.
218 * @param secondary The message to show - second part, additional info.
219 * @param command_after_exit A command to execute when the user acknowledged the text. May be omitted. */
220 virtual void show_message(std::string const &primary, std::string const &secondary = "", SmartPtr<Command> command_after_exit = SmartPtr<Command>());
223 /* events */
224 /** See Activity::timer_event(). */
225 void timer_event(int ms_elapsed);
226 /** See Activity::timer2_event(). */
227 void timer2_event();
229 * To be called from the running environment when the user presses a key.
230 * The keypresses are preprocessed - not all keypresses will get through to the
231 * topmost activity. Also see Activity::keypress_event().
232 * @param keycode A unicode character code, or some special key (see Activity::KeyCodeSpecialKey)
233 * @param gfxlib_keycode Graphics library (sdl/gtk/etc) specific keycode
235 void keypress_event(Activity::KeyCode keycode, int gfxlib_keycode);
236 /** See Activity::redraw_event(). */
237 void redraw_event();
238 /** To be called when the user closes the window of the game. The quit_event_command
239 * set via the set_quit_event_command() will be executed. */
240 void quit_event();
242 /* handling activities and commands */
243 /** Push a newly allocated activity on the top of the activity stack.
244 * Before pushing, the old topmost activity is sent an Activity::hidden_event(),
245 * and the new activity will be sent an Activity::push_event and an Activity::shown_event(),
246 * and finally an Activity::redraw_event(). When popped, the activity will be automatically deleted.
247 * @param the_activity The Activity to push. */
248 void push_activity(Activity *the_activity);
249 /** Pop the topmost activity. Before popping, a hidden_event() is sent. */
250 void pop_activity();
251 /** Pop all activities. Can be used when restarting the application from the
252 * title screen. The no activities command is not necessarily executed, because
253 * there may be some commands left in the queue. */
254 void pop_all_activities();
255 /** Put a command to be executed after processing the event in the queue.
256 * The commands will be executed in the order of queueing. Command objects
257 * are handled via smart pointers; if a pointer to a newly allocated Command
258 * is given as the parameter, it will be automatically deleted.
259 * @param the_command The command to be executed later. */
260 void enqueue_command(SmartPtr<Command> the_command);
261 /** An Activity may call this to trigger executing the restart Command. */
262 void request_restart();
263 /** An Activity may call this to trigger executing the editor Command. */
264 void start_editor();
266 /* supporting objects */
267 /** The PixbufFactory to be used for drawing. Will be deleted by ~App. */
268 PixbufFactory *pixbuf_factory;
269 /** The FontManager to be used for drawing texts. Will be deleted by ~App.
270 * Should use the pixbuf_factory assigned to the App. */
271 FontManager *font_manager;
272 /** The Screen to draw on. Will be deleted by ~App. */
273 Screen *screen;
274 /** The CaveSet. For Activity objects. */
275 CaveSet *caveset;
276 /** Joystick & keyboard input, for the Activity objects. Will be deleted by ~App. */
277 GameInputHandler *gameinput;
279 private:
280 /** The image used by App::clear_screen(). */
281 Pixmap *background_image;
282 /** The stack of the Activity objects handled. */
283 std::stack<Activity *> running_activities;
284 /** Returns the topmost activity, or NULL. */
285 Activity *topmost_activity();
286 /** The commands to be executed after the processing of the events. */
287 std::queue<SmartPtr<Command> > command_queue;
288 /** The command to be executed when all activities have quit. */
289 SmartPtr<Command> no_activity_command;
290 /** The command triggered by App::quit_event(). */
291 SmartPtr<Command> quit_event_command;
292 /** The command triggered by App::request_restart(). */
293 SmartPtr<Command> request_restart_command;
294 /** The command triggered by App::start_editor(). */
295 SmartPtr<Command> start_editor_command;
297 protected:
298 /** Process the commands in the queue. After all commands, check if
299 * there are no activities left; if so, call the no_activity_command.
300 * To be used by the App and descendants. */
301 void process_commands();
304 #endif