X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fbutton.cpp;h=f144bb3317f791c3e776ae0d480627d56c96b2b4;hb=4b985b51e7d2da923d53a61bb5038d11978e9cda;hp=7dfbee4804228a360b27545545c2ef7f1975bed3;hpb=e59a8e5e758978341d5410f09b705c4e969dc9a0;p=supertux.git diff --git a/src/button.cpp b/src/button.cpp index 7dfbee480..f144bb331 100644 --- a/src/button.cpp +++ b/src/button.cpp @@ -1,272 +1,324 @@ +// $Id$ // -// C Implementation: button +// SuperTux +// Copyright (C) 2004 Tobias Glaesser // -// Description: -// -// -// Author: Tobias Glaesser , (C) 2004 -// -// Copyright: See COPYING file that comes with this distribution +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. // +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. // +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA. #include #include #include "setup.h" -#include "screen.h" +#include "screen/screen.h" +#include "screen/drawing_context.h" #include "globals.h" #include "button.h" +#include "camera.h" -void button_load(button_type* pbutton,char* icon_file, char* info, SDLKey shortcut, int x, int y) +Timer Button::popup_timer; + +Button::Button(Surface* button_image, const std::string& ninfo, + SDLKey nshortcut, int x, int y, int mw, int mh) { - char filename[1024]; + popup_timer.init(false); - if(icon_file != NULL) - { - snprintf(filename, 1024, "%s/%s", datadir.c_str(), icon_file); - if(!faccessible(filename)) - snprintf(filename, 1024, "%s/images/icons/default-icon.png", datadir.c_str()); - } - else - { - snprintf(filename, 1024, "%s/images/icons/default-icon.png", datadir.c_str()); - } - texture_load(&pbutton->icon,filename,USE_ALPHA); + if(button_image) + icon.push_back(button_image); - if(info == NULL) - { - pbutton->info = NULL; - } - else - { - pbutton->info = (char*) malloc(sizeof(char)*(strlen(info) + 1)); - strcpy(pbutton->info,info); - } + info = ninfo; - pbutton->shortcut = shortcut; + shortcut = nshortcut; - pbutton->x = x; - pbutton->y = y; - pbutton->w = pbutton->icon.w; - pbutton->h = pbutton->icon.h; - pbutton->tag = -1; - pbutton->state = -1; - pbutton->show_info = NO; - pbutton->bkgd = NULL; + rect.x = x; + rect.y = y; + rect.w = icon[0]->w; + rect.h = icon[0]->h; + tag = -1; + state = BUTTON_NONE; + show_info = false; } -void button_change_icon(button_type* pbutton,char* icon_file) +Button::Button(const std::string& imagefilename, const std::string& ninfo, + SDLKey nshortcut, int x, int y, int mw, int mh) { - char filename[1024]; + popup_timer.init(false); - if(icon_file != NULL) - { - snprintf(filename, 1024, "%s/%s", datadir.c_str(), icon_file); - if(!faccessible(filename)) - snprintf(filename, 1024, "%s/images/icons/default-icon.png", datadir.c_str()); - } - else - { - snprintf(filename, 1024, "%s/images/icons/default-icon.png", datadir.c_str()); - } + add_icon(imagefilename, mw, mh); - texture_free(&pbutton->icon); - texture_load(&pbutton->icon,filename,USE_ALPHA); + info = ninfo; + + shortcut = nshortcut; + + rect.x = x; + rect.y = y; + rect.w = icon[0]->w; + rect.h = icon[0]->h; + tag = -1; + state = BUTTON_NONE; + show_info = false; } -button_type* button_create(char* icon_file, char* info, SDLKey shortcut, int x, int y) +void Button::add_icon(const std::string& icon_file, int mw, int mh) { - button_type* pnew_button = (button_type*) malloc(sizeof(button_type)); - button_load(pnew_button,icon_file, info, shortcut, x, y); - return pnew_button; + char filename[1024]; + + if(!icon_file.empty()) + { + snprintf(filename, 1024, "%s/%s", datadir.c_str(), icon_file.c_str()); + if(!faccessible(filename)) + snprintf(filename, 1024, "%s/images/icons/default-icon.png", datadir.c_str()); + } + else + { + snprintf(filename, 1024, "%s/images/icons/default-icon.png", datadir.c_str()); + } + + if(mw != -1 || mh != -1) + { + icon.push_back(new Surface(filename,USE_ALPHA)); + icon.back()->resize(mw,mh); + } + else + icon.push_back(new Surface(filename,USE_ALPHA)); + } -void button_draw(button_type* pbutton) +void Button::draw(DrawingContext& context) { - fillrect(pbutton->x,pbutton->y,pbutton->w,pbutton->h,75,75,75,200); - fillrect(pbutton->x+1,pbutton->y+1,pbutton->w-2,pbutton->h-2,175,175,175,200); - if(pbutton->bkgd != NULL) + if(state == BUTTON_HOVER) + if(!popup_timer.check()) + show_info = true; + + fillrect(rect.x,rect.y,rect.w,rect.h,75,75,75,200); + fillrect(rect.x+1,rect.y+1,rect.w-2,rect.h-2,175,175,175,200); + + for(std::vector::iterator it = icon.begin(); it != icon.end(); ++it) + context.draw_surface(*it, Vector(rect.x,rect.y), LAYER_GUI); + +/* if(drawable) { - texture_draw(pbutton->bkgd,pbutton->x,pbutton->y,NO_UPDATE); - } - texture_draw(&pbutton->icon,pbutton->x,pbutton->y,NO_UPDATE); - if(pbutton->show_info == YES) - { - char str[80]; - int i = -32; + Camera viewport; + viewport.set_translation(Vector(rect.x, rect.y)); + drawable->draw(viewport, 0); + }*/ - if(0 > pbutton->x - (int)strlen(pbutton->info) * white_small_text.w) - i = pbutton->w + strlen(pbutton->info) * white_small_text.w; + if(show_info) + { + char str[80]; + int i = -32; - if(pbutton->info) - text_draw(&white_small_text, pbutton->info, i + pbutton->x - strlen(pbutton->info) * white_small_text.w, pbutton->y, 1, NO_UPDATE); - sprintf(str,"(%s)", SDL_GetKeyName(pbutton->shortcut)); - text_draw(&white_small_text, str, i + pbutton->x - strlen(str) * white_small_text.w, pbutton->y + white_small_text.h+2, 1, NO_UPDATE); - } - if(pbutton->state == BUTTON_PRESSED) - fillrect(pbutton->x,pbutton->y,pbutton->w,pbutton->h,75,75,75,200); - else if(pbutton->state == BUTTON_HOVER) - fillrect(pbutton->x,pbutton->y,pbutton->w,pbutton->h,150,150,150,128); + if(0 > rect.x - white_small_text->get_text_width(info)) + i = rect.w + (int)white_small_text->get_text_width(info); + + if(!info.empty()) + context.draw_text(white_small_text, info, Vector(i + rect.x - white_small_text->get_text_width(info), rect.y), LAYER_GUI); + sprintf(str,"(%s)", SDL_GetKeyName(shortcut)); + context.draw_text(white_small_text, str, Vector(i + rect.x - white_small_text->get_text_width(str), rect.y + white_small_text->get_height()+2), LAYER_GUI); + } + if(state == BUTTON_PRESSED || state == BUTTON_DEACTIVE) + fillrect(rect.x,rect.y,rect.w,rect.h,75,75,75,200); + else if(state == BUTTON_HOVER) + fillrect(rect.x,rect.y,rect.w,rect.h,150,150,150,128); } -void button_free(button_type* pbutton) +Button::~Button() { - free(pbutton->info); - texture_free(&pbutton->icon); + for(std::vector::iterator it = icon.begin(); it != icon.end(); ++it) + delete (*it); + icon.clear(); + // FIXME TODO XXX: commenting this out fixes the leveleditor quit crash + // probably should be deleted somehow, though + //delete drawable; } -void button_event(button_type* pbutton, SDL_Event *event) +void Button::event(SDL_Event &event) { - SDLKey key = event->key.keysym.sym; + if(state == BUTTON_DEACTIVE) + return; + + SDLKey key = event.key.keysym.sym; - if(event->motion.x > pbutton->x && event->motion.x < pbutton->x + pbutton->w && - event->motion.y > pbutton->y && event->motion.y < pbutton->y + pbutton->h) + if(event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP) + { + if(event.button.x < rect.x || event.button.x >= rect.x + rect.w || + event.button.y < rect.y || event.button.y >= rect.y + rect.h) + return; + + if(event.button.button == SDL_BUTTON_RIGHT) { - if(event->type == SDL_MOUSEBUTTONDOWN) - { - if(event->button.button == SDL_BUTTON_LEFT) - { - pbutton->state = BUTTON_PRESSED; - } - else - { - pbutton->show_info = YES; - } - } - else if(event->type == SDL_MOUSEBUTTONUP) - { - if(event->button.button == SDL_BUTTON_LEFT && pbutton->state == BUTTON_PRESSED) - { - pbutton->state = BUTTON_CLICKED; - } - else if(event->button.button != SDL_BUTTON_LEFT && pbutton->state != BUTTON_PRESSED) - { - pbutton->show_info = YES; - } - } - - if(pbutton->state != BUTTON_PRESSED && pbutton->state != BUTTON_CLICKED) - { - pbutton->state = BUTTON_HOVER; - } + show_info = true; + return; } - else if(event->type != SDL_KEYDOWN && event->type != SDL_KEYUP) + else if(event.type == SDL_MOUSEBUTTONUP && event.button.button == 4) /* Mouse wheel up. */ { - pbutton->state = -1; - if(pbutton->show_info) - { - pbutton->show_info = NO; - } + state = BUTTON_WHEELUP; + return; } - - if(event->type == SDL_KEYDOWN) + else if(event.type == SDL_MOUSEBUTTONUP && event.button.button == 5) /* Mouse wheel down. */ { - if(key == pbutton->shortcut) - pbutton->state = BUTTON_PRESSED; + state = BUTTON_WHEELDOWN; + return; } - else if(event->type == SDL_KEYUP) + + if(event.button.button == SDL_BUTTON_LEFT) + if(event.type == SDL_MOUSEBUTTONDOWN) + state = BUTTON_PRESSED; + else + state = BUTTON_CLICKED; + } + else if(event.type == SDL_MOUSEMOTION) + { + if(event.motion.x < rect.x || event.motion.x >= rect.x + rect.w || + event.motion.y < rect.y || event.motion.y >= rect.y + rect.h) { - if(pbutton->state == BUTTON_PRESSED && key == pbutton->shortcut) - pbutton->state = BUTTON_CLICKED; + state = BUTTON_NONE; } - else if(event->type == SDL_MOUSEMOTION) + else { + state = BUTTON_HOVER; + popup_timer.start(1500); + } - if(pbutton->show_info) - { - pbutton->show_info = NO; - } + if(show_info) + { + show_info = false; } + } + else if(event.type == SDL_KEYDOWN) + { + if(key == shortcut) + state = BUTTON_PRESSED; + } + else if(event.type == SDL_KEYUP) + { + if(state == BUTTON_PRESSED && key == shortcut) + state = BUTTON_CLICKED; + } } -int button_get_state(button_type* pbutton) +int Button::get_state() { - int state; - if(pbutton->state == BUTTON_CLICKED) - { - state = pbutton->state; - pbutton->state = -1; - return state; - } - else - { - return pbutton->state; - } + int rstate; + switch(state) + { + case BUTTON_CLICKED: + case BUTTON_WHEELUP: + case BUTTON_WHEELDOWN: + rstate = state; + state = BUTTON_NONE; + return rstate; + default: + return state; + } } -void button_panel_init(button_panel_type* pbutton_panel, int x, int y, int w, int h) +ButtonPanel::ButtonPanel(int x, int y, int w, int h) { - pbutton_panel->num_items = 0; - pbutton_panel->item = NULL; - pbutton_panel->x = x; - pbutton_panel->y = y; - pbutton_panel->w = w; - pbutton_panel->h = h; - pbutton_panel->hidden = NO; + bw = 32; + bh = 32; + rect.x = x; + rect.y = y; + rect.w = w; + rect.h = h; + hidden = false; + hlast = false; } -button_type* button_panel_event(button_panel_type* pbutton_panel, SDL_Event* event) +Button* ButtonPanel::event(SDL_Event& event) { - if(pbutton_panel->hidden == NO) + if(!hidden) + { + Button* ret = NULL; + for(std::vector::iterator it = item.begin(); it != item.end(); ++it) { - int i; - for(i = 0; i < pbutton_panel->num_items; ++i) - { - button_event(&pbutton_panel->item[i],event); - if(pbutton_panel->item[i].state != -1) - return &pbutton_panel->item[i]; - } - return NULL; + (*it)->event(event); + if((*it)->state != BUTTON_NONE) + { + if(hlast && (*it)->state == BUTTON_CLICKED) + last_clicked = it; + ret = (*it); + } } + return ret; + } else - { - return NULL; - } + { + return NULL; + } } -void button_panel_free(button_panel_type* pbutton_panel) +ButtonPanel::~ButtonPanel() { - int i; - for(i = 0; i < pbutton_panel->num_items; ++i) - { - button_free(&pbutton_panel->item[i]); - } - if(pbutton_panel->num_items) - free(pbutton_panel->item); + for(std::vector::iterator it = item.begin(); it != item.end(); ++it) + { + delete (*it); + } + item.clear(); } -void button_panel_draw(button_panel_type* pbutton_panel) +void ButtonPanel::draw(DrawingContext& context) { - if(pbutton_panel->hidden == NO) + + if(hidden == false) + { + fillrect(rect.x,rect.y,rect.w,rect.h,100,100,100,200); + for(std::vector::iterator it = item.begin(); it != item.end(); ++it) { - int i; - fillrect(pbutton_panel->x,pbutton_panel->y,pbutton_panel->w,pbutton_panel->h,100,100,100,200); - for(i = 0; i < pbutton_panel->num_items; ++i) - { - button_draw(&pbutton_panel->item[i]); - } + (*it)->draw(context); + if(hlast && it == last_clicked) + { + fillrect((*it)->get_pos().x,(*it)->get_pos().y,(*it)->get_pos().w,(*it)->get_pos().h,100,100,100,128); + } } + } } -void button_panel_additem(button_panel_type* pbutton_panel, button_type* pbutton, int tag) +void ButtonPanel::additem(Button* pbutton, int tag) { int max_cols, row, col; - ++pbutton_panel->num_items; - pbutton_panel->item = (button_type*) realloc(pbutton_panel->item, sizeof(button_type) * pbutton_panel->num_items); - memcpy(&pbutton_panel->item[pbutton_panel->num_items-1],pbutton,sizeof(button_type)); - free(pbutton); + item.push_back(pbutton); /* A button_panel takes control of the buttons it contains and arranges them */ - max_cols = pbutton_panel->w / 32; + max_cols = rect.w / bw; + + row = (item.size()-1) / max_cols; + col = (item.size()-1) % max_cols; - row = (pbutton_panel->num_items-1) / max_cols; - col = (pbutton_panel->num_items-1) % max_cols; + item[item.size()-1]->rect.x = rect.x + col * bw; + item[item.size()-1]->rect.y = rect.y + row * bh; + item[item.size()-1]->tag = tag; - pbutton_panel->item[pbutton_panel->num_items-1].x = pbutton_panel->x + col * 32; - pbutton_panel->item[pbutton_panel->num_items-1].y = pbutton_panel->y + row * 32; - pbutton_panel->item[pbutton_panel->num_items-1].tag = tag; +} +void ButtonPanel::set_button_size(int w, int h) +{ + bw = w; + bh = h; } +Button* ButtonPanel::manipulate_button(int i) +{ + if(int(item.size())-1 < i) + return item[item.size()-1]; + else + return item[i]; +} + +void ButtonPanel::highlight_last(bool b) +{ + hlast = b; +}