Atrinik Client  4.0
popup.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
32 #include <global.h>
33 #include <toolkit/string.h>
34 #include <toolkit/x11.h>
35 
39 static popup_struct *popup_head = NULL;
40 
49 {
50  popup_struct *popup;
51  int mx, my;
52 
53  popup = ecalloc(1, sizeof(popup_struct));
54  popup->texture = texture;
55  /* Create the surface used by the popup. */
56  popup->surface = SDL_ConvertSurface(texture_surface(popup->texture), texture_surface(popup->texture)->format, texture_surface(popup->texture)->flags);
57  DL_PREPEND(popup_head, popup);
58 
59  SDL_GetMouseState(&mx, &my);
60  /* Make sure the mouse is no longer moving any widget. */
61  widget_event_move_stop(mx, my);
62 
65 
66  popup->button_left.button.texture = popup->button_right.button.texture = texture_get(TEXTURE_TYPE_CLIENT, "button_round_large");
67  popup->button_left.button.texture_pressed = popup->button_right.button.texture_pressed = texture_get(TEXTURE_TYPE_CLIENT, "button_round_large_down");
68  popup->button_left.button.texture_over = popup->button_right.button.texture_over = texture_get(TEXTURE_TYPE_CLIENT, "button_round_large_over");
69 
70  popup->button_left.x = 6;
71  popup->button_left.y = 6;
72 
73  popup->button_right.x = popup->surface->w - texture_surface(popup->button_right.button.texture)->w - 6;
74  popup->button_right.y = 6;
75  popup->button_right.text = estrdup("X");
76 
77  popup->selection_start = popup->selection_end = -1;
78  popup->redraw = 1;
79  popup->modal = 1;
80 
81  return popup;
82 }
83 
89 static void popup_button_free(popup_button *button)
90 {
91  if (button->text) {
92  efree(button->text);
93  }
94 
95  button_destroy(&button->button);
96 }
97 
102 {
103  if (popup->destroy_callback_func && !popup->destroy_callback_func(popup)) {
104  return;
105  }
106 
107  DL_DELETE(popup_head, popup);
108  SDL_FreeSurface(popup->surface);
109 
110  if (popup->buf) {
111  efree(popup->buf);
112  }
113 
114  if (popup->custom_data) {
115  efree(popup->custom_data);
116  }
117 
120 
121  efree(popup);
122 
124 }
125 
130 {
131  popup_struct *popup, *tmp;
132 
133  DL_FOREACH_SAFE(popup_head, popup, tmp)
134  {
135  popup_destroy(popup);
136  }
137 }
138 
146 static void popup_button_show(popup_struct *popup, popup_button *button)
147 {
148  if (button->button.texture) {
149  button->button.x = popup->x + button->x;
150  button->button.y = popup->y + button->y;
151  button_show(&button->button, button->text ? button->text : "");
152  }
153 }
154 
161 {
162  SDL_Rect box;
163 
164  if (!popup->disable_texture_drawing) {
165  surface_show(popup->surface, 0, 0, NULL, texture_surface(popup->texture));
166  }
167 
168  /* Calculate the popup's X/Y positions. */
169  popup->x = ScreenSurface->w / 2 - popup->surface->w / 2;
170  popup->y = ScreenSurface->h / 2 - popup->surface->h / 2;
171 
172  /* Handle drawing inside the popup. */
173  if (popup->draw_func) {
174  text_offset_set(popup->x, popup->y);
175 
176  if (!popup->draw_func(popup)) {
178  popup_destroy(popup);
179  return;
180  }
181 
183  }
184 
185  /* Show the popup in the middle of the screen. */
186  box.x = popup->x;
187  box.y = popup->y;
188  SDL_BlitSurface(popup->surface, NULL, ScreenSurface, &box);
189 
190  popup_button_show(popup, &popup->button_left);
191  popup_button_show(popup, &popup->button_right);
192 
193  if (popup->draw_post_func) {
194  if (!popup->draw_post_func(popup)) {
195  popup_destroy(popup);
196  return;
197  }
198  }
199 }
200 
205 {
206  popup_struct *popup, *tmp;
207 
208  DL_FOREACH_REVERSE_SAFE(popup_head, popup, tmp)
209  {
210  popup_render(popup);
211  }
212 }
213 
225 static int popup_button_handle_event(popup_button *button, SDL_Event *event)
226 {
227  if (button->text && button_event(&button->button, event)) {
228  if (button->event_func && button->event_func(button)) {
229  return -1;
230  }
231 
232  return 1;
233  }
234 
235  return 0;
236 }
237 
245 int popup_handle_event(SDL_Event *event)
246 {
247  int ret;
248 
249  if (popup_head && !popup_head->modal && event->type == SDL_MOUSEBUTTONDOWN && !(event->motion.x >= popup_head->x && event->motion.x < popup_head->x + texture_surface(popup_head->texture)->w && event->motion.y >= popup_head->y && event->motion.y < popup_head->y + texture_surface(popup_head->texture)->h)) {
250  if (popup_head->destroy_on_switch) {
251  popup_destroy(popup_head);
252  return 1;
253  }
254  }
255 
256  /* No popup is visible. */
257  if (!popup_head) {
258  return 0;
259  }
260 
261  if (popup_head->clipboard_copy_func) {
262  if (event->type == SDL_KEYDOWN && keybind_command_matches_event("?COPY", &event->key)) {
263  const char *contents;
264  int64_t start, end;
265  char *str;
266 
267  contents = popup_head->clipboard_copy_func(popup_head);
268 
269  if (!contents) {
270  return 1;
271  }
272 
273  start = popup_head->selection_start;
274  end = popup_head->selection_end;
275 
276  if (end < start) {
277  start = popup_head->selection_end;
278  end = popup_head->selection_start;
279  }
280 
281  if (end - start <= 0) {
282  return 1;
283  }
284 
285  /* Get the string to copy, depending on the start and end positions.
286  * */
287  str = emalloc(sizeof(char) * (end - start + 1 + 1));
288  memcpy(str, contents + start, end - start + 1);
289  str[end - start + 1] = '\0';
290  x11_clipboard_set(SDL_display, SDL_window, str);
291  efree(str);
292 
293  return 1;
294  } else if ((event->type == SDL_MOUSEBUTTONDOWN || event->type == SDL_MOUSEBUTTONUP || event->type == SDL_MOUSEMOTION) && event->motion.x >= popup_head->x && event->motion.x < popup_head->x + texture_surface(popup_head->texture)->w && event->motion.y >= popup_head->y && event->motion.y < popup_head->y + texture_surface(popup_head->texture)->h) {
295  if (event->type == SDL_MOUSEMOTION) {
296  popup_head->redraw = 1;
297 
298  if (event->button.button == SDL_BUTTON_LEFT) {
299  popup_head->selection_started = 1;
300  }
301  } else if (event->button.button == SDL_BUTTON_LEFT) {
302  if (event->type == SDL_MOUSEBUTTONUP) {
303  popup_head->selection_started = 0;
304  } else if (event->type == SDL_MOUSEBUTTONDOWN) {
305  popup_head->selection_started = 0;
306  popup_head->selection_start = -1;
307  popup_head->selection_end = -1;
308  popup_head->redraw = 1;
309  }
310  }
311  }
312  }
313 
314  /* Handle custom events? */
315  if (popup_head->event_func) {
316  ret = popup_head->event_func(popup_head, event);
317 
318  if (ret != -1) {
319  return ret;
320  }
321  }
322 
323  /* Key is down. */
324  if (event->type == SDL_KEYDOWN) {
325  /* Escape, destroy the popup. */
326  if (event->key.keysym.sym == SDLK_ESCAPE) {
327  popup_destroy(popup_head);
328  }
329  } else if ((ret = popup_button_handle_event(&popup_head->button_left, event))) {
330  return 1;
331  } else if ((ret = popup_button_handle_event(&popup_head->button_right, event))) {
332  if (ret == 1) {
333  popup_destroy(popup_head);
334  }
335 
336  return 1;
337  }
338 
339  return 1;
340 }
341 
348 {
349  return popup_head;
350 }
351 
359 void popup_button_set_text(popup_button *button, const char *text)
360 {
361  if (button->text) {
362  efree(button->text);
363  }
364 
365  button->text = text ? estrdup(text) : NULL;
366 }
367 
375 {
376  return popup_get_head() != NULL;
377 }
char * text
Definition: popup.h:44
int(* event_func)(struct popup_struct *popup, SDL_Event *event)
Definition: popup.h:148
int(* draw_func)(struct popup_struct *popup)
Definition: popup.h:127
int(* draw_post_func)(struct popup_struct *popup)
Definition: popup.h:137
SDL_Surface * texture_surface(texture_struct *texture)
Definition: texture.c:303
int button_event(button_struct *button, SDL_Event *event)
Definition: button.c:222
int(* destroy_callback_func)(struct popup_struct *popup)
Definition: popup.h:159
void * custom_data
Definition: popup.h:78
int y
Definition: popup.h:41
void button_destroy(button_struct *button)
Definition: button.c:94
button_struct button
Definition: popup.h:47
int x
Definition: popup.h:87
void keybind_state_ensure(void)
Definition: keybind.c:535
void text_offset_reset(void)
Definition: text.c:391
texture_struct * texture_get(texture_type_t type, const char *name)
Definition: texture.c:279
SDL_Surface * ScreenSurface
Definition: main.c:47
const char *(* clipboard_copy_func)(struct popup_struct *popup)
Definition: popup.h:168
void text_offset_set(int x, int y)
Definition: text.c:381
uint8_t redraw
Definition: popup.h:114
texture_struct * texture_over
Definition: button.h:67
uint8_t selection_started
Definition: popup.h:111
int(* event_func)(struct popup_button *button)
Definition: popup.h:56
void button_create(button_struct *button)
Definition: button.c:65
x11_display_type SDL_display
Definition: video.c:36
char * buf
Definition: popup.h:81
texture_struct * texture
Definition: button.h:61
int keybind_command_matches_event(const char *cmd, SDL_KeyboardEvent *event)
Definition: keybind.c:391
int y
Definition: popup.h:90
popup_button button_left
Definition: popup.h:93
texture_struct * texture_pressed
Definition: button.h:73
int x
Definition: popup.h:38
void surface_show(SDL_Surface *surface, int x, int y, SDL_Rect *srcrect, SDL_Surface *src)
Definition: sprite.c:761
x11_window_type SDL_window
Definition: video.c:40
popup_button button_right
Definition: popup.h:96
SDL_Surface * surface
Definition: popup.h:65
int64_t selection_end
Definition: popup.h:108
void button_show(button_struct *button, const char *text)
Definition: button.c:161
texture_struct * texture
Definition: popup.h:70
uint8_t disable_texture_drawing
Definition: popup.h:75
int64_t selection_start
Definition: popup.h:105