Atrinik Client 2.5
toolkit/button.c
Go to the documentation of this file.
00001 /************************************************************************
00002 *            Atrinik, a Multiplayer Online Role Playing Game            *
00003 *                                                                       *
00004 *    Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team    *
00005 *                                                                       *
00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game)     *
00007 * and Crossfire (Multiplayer game for X-windows).                       *
00008 *                                                                       *
00009 * This program is free software; you can redistribute it and/or modify  *
00010 * it under the terms of the GNU General Public License as published by  *
00011 * the Free Software Foundation; either version 2 of the License, or     *
00012 * (at your option) any later version.                                   *
00013 *                                                                       *
00014 * This program is distributed in the hope that it will be useful,       *
00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00017 * GNU General Public License for more details.                          *
00018 *                                                                       *
00019 * You should have received a copy of the GNU General Public License     *
00020 * along with this program; if not, write to the Free Software           *
00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.             *
00022 *                                                                       *
00023 * The author can be reached at admin@atrinik.org                        *
00024 ************************************************************************/
00025 
00030 #include <global.h>
00031 
00035 static uint32 ticks = 0;
00038 static uint32 ticks_delay;
00039 
00061 int button_show(int bitmap_id, int bitmap_id_over, int bitmap_id_clicked, int x, int y, const char *text, int font, const char *color, const char *color_shadow, const char *color_over, const char *color_over_shadow, uint64 flags)
00062 {
00063     _Sprite *sprite = Bitmaps[bitmap_id];
00064     int mx, my, ret = 0, state;
00065     const char *use_color = color, *use_color_shadow = color_shadow;
00066 
00067     /* Get state of the mouse and the x/y. */
00068     state = SDL_GetMouseState(&mx, &my);
00069 
00070     /* Is the mouse inside the button, and also not on top of button's
00071      * transparent pixel? */
00072     if (mx > x && mx < x + sprite->bitmap->w && my > y && my < y + sprite->bitmap->h)
00073     {
00074         /* Change color. */
00075         use_color = color_over;
00076         use_color_shadow = color_over_shadow;
00077 
00078         /* Left button clicked? */
00079         if (state == SDL_BUTTON_LEFT)
00080         {
00081             /* Change bitmap. */
00082             if (bitmap_id_clicked != -1)
00083             {
00084                 sprite = Bitmaps[bitmap_id_clicked];
00085             }
00086 
00087             if (!ticks || SDL_GetTicks() - ticks > ticks_delay)
00088             {
00089                 ticks_delay = ticks ? 125 : 700;
00090                 ticks = SDL_GetTicks();
00091                 ret = 1;
00092             }
00093         }
00094         else
00095         {
00096             if (bitmap_id_over != -1)
00097             {
00098                 sprite = Bitmaps[bitmap_id_over];
00099             }
00100 
00101             ticks = 0;
00102         }
00103     }
00104 
00105     /* Draw the bitmap. */
00106     sprite_blt(sprite, x, y, NULL, NULL);
00107 
00108     /* If text was passed, draw it as well. */
00109     if (text)
00110     {
00111         string_blt_shadow(ScreenSurface, font, text, x + sprite->bitmap->w / 2 - string_get_width(font, text, flags) / 2, y + sprite->bitmap->h / 2 - FONT_HEIGHT(font) / 2, use_color, use_color_shadow, flags, NULL);
00112     }
00113 
00114     return ret;
00115 }
00116 
00122 static _Sprite *button_determine_sprite(button_struct *button)
00123 {
00124     if (button->pressed && button->bitmap_pressed != -1)
00125     {
00126         return Bitmaps[button->bitmap_pressed];
00127     }
00128     else if (button->mouse_over && button->bitmap_over != -1)
00129     {
00130         return Bitmaps[button->bitmap_over];
00131     }
00132     else
00133     {
00134         return Bitmaps[button->bitmap];
00135     }
00136 }
00137 
00141 void button_create(button_struct *button)
00142 {
00143     /* Initialize default values. */
00144     button->x = button->y = 0;
00145     button->bitmap = BITMAP_BUTTON;
00146     button->bitmap_over = -1;
00147     button->bitmap_pressed = BITMAP_BUTTON_DOWN;
00148     button->font = FONT_ARIAL10;
00149     button->flags = 0;
00150     button->color = COLOR_WHITE;
00151     button->color_shadow = COLOR_BLACK;
00152     button->color_over = COLOR_HGOLD;
00153     button->color_over_shadow = COLOR_BLACK;
00154 
00155     button->mouse_over = button->pressed = 0;
00156 }
00157 
00162 void button_render(button_struct *button, const char *text)
00163 {
00164     _Sprite *sprite;
00165 
00166     /* Make sure the mouse is still over the button. */
00167     if (button->mouse_over)
00168     {
00169         int mx, my;
00170 
00171         SDL_GetMouseState(&mx, &my);
00172 
00173         if (!BUTTON_MOUSE_OVER(button, mx, my, Bitmaps[button->bitmap]))
00174         {
00175             button->mouse_over = 0;
00176         }
00177     }
00178 
00179     sprite = button_determine_sprite(button);
00180     sprite_blt(sprite, button->x, button->y, NULL, NULL);
00181 
00182     if (text)
00183     {
00184         const char *color, *color_shadow;
00185 
00186         if (button->mouse_over)
00187         {
00188             color = button->color_over;
00189             color_shadow = button->color_over_shadow;
00190         }
00191         else
00192         {
00193             color = button->color;
00194             color_shadow = button->color_shadow;
00195         }
00196 
00197         string_blt_shadow(ScreenSurface, button->font, text, button->x + sprite->bitmap->w / 2 - string_get_width(button->font, text, button->flags) / 2, button->y + sprite->bitmap->h / 2 - FONT_HEIGHT(button->font) / 2, color, color_shadow, button->flags, NULL);
00198     }
00199 
00200     if (button->repeat_func && button->pressed && SDL_GetTicks() - button->pressed_ticks > button->pressed_repeat_ticks)
00201     {
00202         button->repeat_func(button);
00203         button->pressed_ticks = SDL_GetTicks();
00204         button->pressed_repeat_ticks = 150;
00205     }
00206 }
00207 
00213 int button_event(button_struct *button, SDL_Event *event)
00214 {
00215     _Sprite *sprite;
00216     int old_mouse_over;
00217 
00218     if (event->type != SDL_MOUSEBUTTONUP && event->type != SDL_MOUSEBUTTONDOWN && event->type != SDL_MOUSEMOTION)
00219     {
00220         return 0;
00221     }
00222 
00223     /* Mouse button is released, the button is no longer being pressed. */
00224     if (event->type == SDL_MOUSEBUTTONUP)
00225     {
00226         button->pressed = 0;
00227         return 0;
00228     }
00229 
00230     old_mouse_over = button->mouse_over;
00231     /* Always reset this. */
00232     button->mouse_over = 0;
00233 
00234     /* The button is disabled, we don't care about the mouse. */
00235     if (button->disabled)
00236     {
00237         return 0;
00238     }
00239 
00240     sprite = button_determine_sprite(button);
00241 
00242     if (BUTTON_MOUSE_OVER(button, event->motion.x, event->motion.y, sprite))
00243     {
00244         /* Left mouse click, the button has been pressed. */
00245         if (event->type == SDL_MOUSEBUTTONDOWN && event->button.button == SDL_BUTTON_LEFT)
00246         {
00247             button->pressed = 1;
00248             button->pressed_ticks = SDL_GetTicks();
00249             button->pressed_repeat_ticks = 750;
00250             return 1;
00251         }
00252         else
00253         {
00254             button->mouse_over = 1;
00255 
00256             /* Do not reset hover ticks if the previous state was already
00257              * in highlight mode. */
00258             if (!old_mouse_over)
00259             {
00260                 button->hover_ticks = SDL_GetTicks();
00261             }
00262         }
00263     }
00264 
00265     return 0;
00266 }
00267 
00273 void button_tooltip(button_struct *button, int font, const char *text)
00274 {
00275     /* Sanity check. */
00276     if (!button || !text)
00277     {
00278         return;
00279     }
00280 
00281     /* Render the tooltip if the mouse is over the button, it's not
00282      * pressed, and enough time has passed since the button was
00283      * highlighted. */
00284     if (button->mouse_over && !button->pressed && SDL_GetTicks() - button->hover_ticks > BUTTON_TOOLTIP_DELAY)
00285     {
00286         int mx, my;
00287 
00288         SDL_GetMouseState(&mx, &my);
00289 
00290         tooltip_create(mx, my, font, text);
00291     }
00292 }