a first implementation of doors to switch between sectors
[supertux.git] / src / button.cpp
index c348a23..15b2be1 100644 (file)
+//  $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"
 
-timer_type Button::popup_timer;
+// TODO
+#if 0
 
-Button::Button(std::string icon_file, std::string ninfo, SDLKey nshortcut, int x, int y, int mw, int mh)
+Timer Button::popup_timer;
+
+Button::Button(Surface* button_image, const std::string& ninfo,
+    SDLKey nshortcut, int x, int y, int mw, int mh)
 {
   popup_timer.init(false);
 
-  char filename[1024];
+  if(button_image)
+    icon.push_back(button_image);
 
-  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());
-    }
+  info = ninfo;
 
-  if(mw != -1 || mh != -1)
-    {
-      texture_load(&icon,filename,USE_ALPHA);
-      if(mw != -1)
-        icon.w = mw;
-      if(mh != -1)
-        icon.h = mh;
-
-      SDL_Rect dest;
-      dest.x = 0;
-      dest.y = 0;
-      dest.w = icon.w;
-      dest.h = icon.h;
-      SDL_SoftStretch(icon.sdl_surface, NULL, icon.sdl_surface, &dest);
-    }
-  else
-    texture_load(&icon,filename,USE_ALPHA);
+  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::Button(const std::string& imagefilename, const std::string& ninfo,
+    SDLKey nshortcut, int x, int y, int mw, int mh)
+{
+  popup_timer.init(false);
+
+  add_icon(imagefilename, mw, mh);
+  
   info = ninfo;
 
   shortcut = nshortcut;
 
   rect.x = x;
   rect.y = y;
-  rect.w = icon.w;
-  rect.h = icon.h;
+  rect.w = icon[0]->w;
+  rect.h = icon[0]->h;
   tag = -1;
   state = BUTTON_NONE;
   show_info = false;
-  bkgd = NULL;
+  drawable = NULL;
 }
 
-void Button::change_icon(std::string icon_file, int mw, int mh)
+void Button::add_icon(const std::string& icon_file, int mw, int mh)
 {
   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/%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));
 
-  texture_free(&icon);
-  texture_load(&icon,filename,USE_ALPHA);
 }
 
 void Button::draw()
 {
   if(state == BUTTON_HOVER)
     if(!popup_timer.check())
-     show_info = true;
+      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);
-  if(bkgd != NULL)
-    {
-      texture_draw(bkgd,rect.x,rect.y);
-    }
-  texture_draw(&icon,rect.x,rect.y);
-  if(show_info)
-    {
-      char str[80];
-      int i = -32;
 
-      if(0 > rect.x - (int)strlen(info.c_str()) * white_small_text.w)
-        i = rect.w + strlen(info.c_str()) * white_small_text.w;
+  for(std::vector<Surface*>::iterator it = icon.begin(); it != icon.end(); ++it)
+    (*it)->draw(rect.x,rect.y);
 
-      if(!info.empty())
-        text_draw(&white_small_text, info.c_str(), i + rect.x - strlen(info.c_str()) * white_small_text.w, rect.y, 1);
-      sprintf(str,"(%s)", SDL_GetKeyName(shortcut));
-      text_draw(&white_small_text, str, i + rect.x - strlen(str) * white_small_text.w, rect.y + white_small_text.h+2, 1);
-    }
-  if(state == BUTTON_PRESSED)
+  if(drawable)
+  {
+    Camera viewport;
+    viewport.set_translation(Vector(rect.x, rect.y));
+    drawable->draw(viewport, 0);
+  }
+
+  if(show_info)
+  {
+    char str[80];
+    int i = -32;
+
+    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);
@@ -121,93 +139,97 @@ void Button::draw()
 
 Button::~Button()
 {
-  texture_free(&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(SDL_Event &event)
 {
+  if(state == BUTTON_DEACTIVE)
+    return;
+
   SDLKey key = event.key.keysym.sym;
 
-  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(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)
-            {
-              state = BUTTON_PRESSED;
-            }
-          else
-            {
-              show_info = true;
-            }
-        }
-      else if(event.type == SDL_MOUSEBUTTONUP)
-        {
-          if(event.button.button == SDL_BUTTON_LEFT && state == BUTTON_PRESSED)
-            {
-              state = BUTTON_CLICKED;
-            }
-          else if(event.button.button != SDL_BUTTON_LEFT && state != BUTTON_PRESSED)
-            {
-              show_info = true;
-            }
-        }
-
-      if(state != BUTTON_PRESSED && state != BUTTON_CLICKED)
-        {
-          state = BUTTON_HOVER;
-          mouse_cursor->set_state(MC_LINK);
-        }
+      show_info = true;
+      return;
     }
-  else if((event.type != SDL_KEYDOWN && event.type != SDL_KEYUP) || event.type == SDL_MOUSEMOTION)
+    else if(event.type == SDL_MOUSEBUTTONUP && event.button.button == 4) /* Mouse wheel up. */
     {
-      state = BUTTON_NONE;
-      if(show_info)
-        {
-          show_info = false;
-        }
+      state = BUTTON_WHEELUP;
+      return;
     }
-
-  if(event.type == SDL_KEYDOWN)
+    else if(event.type == SDL_MOUSEBUTTONUP && event.button.button == 5) /* Mouse wheel down. */
     {
-      if(key == shortcut)
-        state = BUTTON_PRESSED;
+      state = BUTTON_WHEELDOWN;
+      return;
     }
-  else if(event.type == SDL_KEYUP)
-    {
-      if(state == BUTTON_PRESSED && key == shortcut)
+
+    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)
+    {
+      state = BUTTON_NONE;
+    }
+    else
     {
+      state = BUTTON_HOVER;
       popup_timer.start(1500);
-    
-      if(show_info)
-        {
-          show_info = false;
-        }
     }
-    
+
+    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()
 {
   int rstate;
-  if(state == BUTTON_CLICKED)
-    {
-      rstate = state;
-      state = BUTTON_NONE;
-      return rstate;
-    }
-  else
-    {
-      return state;
-    }
+  switch(state)
+  {
+  case BUTTON_CLICKED:
+  case BUTTON_WHEELUP:
+  case BUTTON_WHEELDOWN:
+    rstate = state;
+    state = BUTTON_NONE;
+    return rstate;
+  default:
+    return state;
+  }
 }
 
 ButtonPanel::ButtonPanel(int x, int y, int w, int h)
-{ 
+{
   bw = 32;
   bh = 32;
   rect.x = x;
@@ -215,32 +237,38 @@ ButtonPanel::ButtonPanel(int x, int y, int w, int h)
   rect.w = w;
   rect.h = h;
   hidden = false;
+  hlast = false;
 }
 
 Button* ButtonPanel::event(SDL_Event& event)
 {
   if(!hidden)
+  {
+  Button* ret = NULL;
+    for(std::vector<Button*>::iterator it = item.begin(); it != item.end(); ++it)
     {
-      for(std::vector<Button*>::iterator it = item.begin(); it != item.end(); ++it)
-        {
-          (*it)->event(event);
-          if((*it)->state != BUTTON_NONE)
-            return (*it);
-        }
-      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;
+  }
 }
 
 ButtonPanel::~ButtonPanel()
 {
   for(std::vector<Button*>::iterator it = item.begin(); it != item.end(); ++it)
-    {
-      delete (*it);
-    }
+  {
+    delete (*it);
+  }
   item.clear();
 }
 
@@ -248,13 +276,17 @@ void ButtonPanel::draw()
 {
 
   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)
     {
-      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)
-        {
-          (*it)->draw();
-        }
+      (*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 ButtonPanel::additem(Button* pbutton, int tag)
@@ -276,3 +308,24 @@ void ButtonPanel::additem(Button* pbutton, int 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
+
+