+// $Id$
//
-// C Implementation: button
+// SuperTux
+// Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
//
-// Description:
-//
-//
-// Author: Tobias Glaesser <tobi.web@gmx.de>, (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 <string.h>
#include <stdlib.h>
#include "setup.h"
-#include "screen.h"
+#include "screen/screen.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)
+// TODO
+#if 0
+
+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", DATA_PREFIX, icon_file);
- if(!faccessible(filename))
- snprintf(filename, 1024, "%s/images/icons/default-icon.png", DATA_PREFIX);
- }
- else
- {
- snprintf(filename, 1024, "%s/images/icons/default-icon.png", DATA_PREFIX);
- }
- 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;
+ drawable = NULL;
}
-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", DATA_PREFIX, icon_file);
- if(!faccessible(filename))
- snprintf(filename, 1024, "%s/images/icons/default-icon.png", DATA_PREFIX);
- }
- else
- {
- snprintf(filename, 1024, "%s/images/icons/default-icon.png", DATA_PREFIX);
- }
+ 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;
+ drawable = NULL;
}
-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()
{
- 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<Surface*>::iterator it = icon.begin(); it != icon.end(); ++it)
+ (*it)->draw(rect.x,rect.y);
+
+ if(drawable)
{
- texture_draw(pbutton->bkgd,pbutton->x,pbutton->y,NO_UPDATE);
+ Camera viewport;
+ viewport.set_translation(Vector(rect.x, rect.y));
+ drawable->draw(viewport, 0);
}
- texture_draw(&pbutton->icon,pbutton->x,pbutton->y,NO_UPDATE);
- if(pbutton->show_info == YES)
- {
- char str[80];
- int i = -32;
- 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 == BN_PRESSED)
- fillrect(pbutton->x,pbutton->y,pbutton->w,pbutton->h,75,75,75,200);
- else if(pbutton->state == BN_HOVER)
- fillrect(pbutton->x,pbutton->y,pbutton->w,pbutton->h,150,150,150,128);
+ if(0 > rect.x - (int)strlen(info.c_str()) * white_small_text->w)
+ i = rect.w + strlen(info.c_str()) * white_small_text->w;
+
+ if(!info.empty())
+ white_small_text->draw(info.c_str(), i + rect.x - strlen(info.c_str()) * white_small_text->w, rect.y, 1);
+ sprintf(str,"(%s)", SDL_GetKeyName(shortcut));
+ white_small_text->draw(str, i + rect.x - strlen(str) * white_small_text->w, rect.y + white_small_text->h+2, 1);
+ }
+ 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<Surface*>::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 = BN_PRESSED;
- }
- else
- {
- pbutton->show_info = YES;
- }
- }
- else if(event->type == SDL_MOUSEBUTTONUP)
- {
- if(event->button.button == SDL_BUTTON_LEFT && pbutton->state == BN_PRESSED)
- {
- pbutton->state = BN_CLICKED;
- }
- else if(event->button.button != SDL_BUTTON_LEFT && pbutton->state != BN_PRESSED)
- {
- pbutton->show_info = YES;
- }
- }
-
- if(pbutton->state != BN_PRESSED && pbutton->state != BN_CLICKED)
- {
- pbutton->state = BN_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 = BN_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 == BN_PRESSED && key == pbutton->shortcut)
- pbutton->state = BN_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 == BN_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<Button*>::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<Button*>::iterator it = item.begin(); it != item.end(); ++it)
+ {
+ delete (*it);
+ }
+ item.clear();
}
-void button_panel_draw(button_panel_type* pbutton_panel)
+void ButtonPanel::draw()
{
- if(pbutton_panel->hidden == NO)
+
+ if(hidden == false)
+ {
+ fillrect(rect.x,rect.y,rect.w,rect.h,100,100,100,200);
+ for(std::vector<Button*>::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();
+ 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 = (pbutton_panel->num_items-1) / max_cols;
- col = (pbutton_panel->num_items-1) % max_cols;
+ row = (item.size()-1) / max_cols;
+ col = (item.size()-1) % max_cols;
- 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;
+ 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;
}
+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;
+}
+#endif
+
+