menulist.cc

Go to the documentation of this file.
00001 /*
00002  *  Copyright (C) 2000-2002  The Exult Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 #ifdef HAVE_CONFIG_H
00020 #  include <config.h>
00021 #endif
00022 
00023 #include "menulist.h"
00024 #include "exult.h"
00025 #include "font.h"
00026 #include "gamewin.h"
00027 #include "mouse.h"
00028 #include "rect.h"
00029 #include "shapeid.h"
00030 
00031 // MenuEntry: a selectable menu entry (a button)
00032 MenuEntry::MenuEntry(Shape_frame *on, Shape_frame *off, int xpos, int ypos)
00033 {
00034   frame_on = on;
00035   frame_off = off;
00036   int max_width = on->get_width()>off->get_width()?on->get_width():off->get_width();
00037   int max_height = on->get_height()>off->get_height()?on->get_height():off->get_height();
00038   x = xpos;
00039   y1 = y = ypos;
00040   x1 = xpos-max_width/2;
00041   x2 = x1+max_width;
00042   y2 = y1+max_height;
00043   selected = false;
00044   dirty = true;
00045 } 
00046 
00047 void MenuEntry::paint(Game_window *gwin)
00048 {
00049         if (!dirty) return;
00050   dirty = false;
00051 
00052   Shape_frame *shape;
00053   if(selected)
00054     shape = frame_on;
00055   else
00056     shape = frame_off;
00057   Shape_manager::get_instance()->paint_shape(
00058           x-shape->get_width()/2, y, shape);
00059   gwin->get_win()->show(x1,y1,x2-x1+1,y2-y1+1); 
00060 }
00061 
00062 bool MenuEntry::handle_event(SDL_Event& event)
00063 {
00064   return((event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_RETURN) ||
00065          event.type == SDL_MOUSEBUTTONUP);
00066 }
00067 
00068 // MenuChoice: a multiple-choice menu entry
00069 MenuChoice::MenuChoice(Shape_frame *on, Shape_frame *off, int xpos, int ypos, Font *fnt)
00070 {
00071   frame_on = on;
00072   frame_off = off;
00073   int max_width = on->get_width()>off->get_width()?on->get_width():off->get_width();
00074   int max_height = on->get_height()>off->get_height()?on->get_height():off->get_height();
00075   x = xpos;
00076   x1 = x-max_width;
00077   y1 = y = ypos;
00078   x2 = x1 + max_width;
00079   y2 = y1 + max_height;
00080   selected = false;
00081   choice = -1;
00082   font = fnt;
00083   max_choice_width = 0;
00084   choices = new std::vector<std::string>();
00085 }
00086 
00087 void MenuChoice::add_choice(const char *s)
00088 {
00089   choices->push_back(std::string(s));
00090   int len = font->get_text_width(s);
00091   max_choice_width = (len>max_choice_width)?len:max_choice_width;
00092   x2 = x+32+max_choice_width;
00093 }
00094 
00095 void MenuChoice::paint(Game_window *gwin)
00096 {
00097         if (!dirty) return;
00098   dirty = false;
00099 
00100   Shape_frame *shape;
00101   if(selected)
00102     shape = frame_on;
00103   else
00104     shape = frame_off;
00105 
00106   Shape_manager::get_instance()->paint_shape(
00107           x-shape->get_width(), y, shape);
00108   gwin->get_win()->show(x1,y1,x2-x1+1,y2-y1+1);
00109   if(choice>=0) {
00110     gwin->get_win()->fill8(0, max_choice_width, font->get_text_height(), x+32, y);
00111     font->draw_text(gwin->get_win()->get_ib8(), 
00112           x+32, y, (*choices)[choice].c_str());
00113     gwin->get_win()->show(x+32,y, x+32+max_choice_width, y+font->get_text_height());
00114   }
00115 }
00116 
00117 bool MenuChoice::handle_event(SDL_Event& event)
00118 {
00119   if(event.type==SDL_MOUSEBUTTONUP) {
00120     dirty = true;
00121     choice++;
00122     if(choice>=choices->size())
00123       choice = 0;
00124   } else if(event.type==SDL_KEYDOWN) {
00125     switch(event.key.keysym.sym) {
00126     case SDLK_LEFT:
00127       dirty = true;
00128       choice--;
00129       if(choice<0)
00130         choice = choices->size()-1;
00131       break;
00132     case SDLK_RIGHT:
00133       dirty = true;
00134             choice++;
00135       if(choice>=choices->size())
00136         choice = 0;
00137       break;
00138     default:
00139       break;
00140     }
00141   }
00142   return false;
00143 }
00144 
00145 MenuList::~MenuList()
00146 {
00147   MenuObject *entry;
00148   for(int i=0; i<entries->size(); i++) {
00149     entry = (*entries)[i];
00150     delete entry;
00151   }
00152   delete entries;
00153 }
00154 
00155 void MenuList::set_selection(int sel)
00156 {
00157   MenuObject *entry;
00158 
00159   // deselect the previous entry
00160   if (selected) {
00161     entry = (*entries)[selection];
00162     entry->set_selected(false);
00163   }
00164 
00165   // select the new one
00166   selected = true;
00167   selection = sel;
00168   entry = (*entries)[selection];
00169   entry->set_selected(true);
00170 }
00171 
00172 void MenuList::set_selection(int x, int y)
00173 {
00174   MenuObject *entry;
00175 
00176   // deselect the previous one, unless nothing changed
00177   if (selected) {
00178           entry = (*entries)[selection];
00179           if (entry->is_mouse_over(x, y))
00180                   return;
00181 
00182                 entry->set_selected(false);
00183   }
00184   
00185   // select the new one, and return when found
00186   for(int i=0; i<entries->size(); i++) {
00187     entry = (*entries)[i];
00188     if(entry->is_mouse_over(x, y)) {
00189       entry->set_selected(true);
00190       selected = true;
00191       selection = i;
00192       return;
00193     }
00194   }
00195 
00196   // nothing has been selected
00197   selected = false;
00198 }
00199 
00200 int MenuList::handle_events(Game_window *gwin, Mouse *mouse)
00201 {
00202         unsigned char mouse_visible;
00203   int count = entries->size();
00204   bool exit_loop = false;
00205   int scale = gwin->get_fastmouse() ? 1 : gwin->get_win()->get_scale();
00206   SDL_Event event;
00207 
00208   for(int i=0; i<count; i++)
00209     (*entries)[i]->dirty = true;
00210 
00211   gwin->show(1);
00212   mouse->show();
00213   do {
00214           mouse_visible = mouse->is_onscreen();
00215     if (mouse_visible) mouse->hide();
00216 
00217     // redraw items if they're dirty
00218     for(int i=0; i<count; i++) {
00219       MenuObject *entry = (*entries)[i];
00220       entry->paint(gwin);
00221     }
00222 
00223     // redraw mouse if visible
00224     if (mouse_visible) {
00225             mouse->show();
00226       mouse->blit_dirty();
00227     }
00228 
00229     SDL_WaitEvent(&event);
00230     if(event.type==SDL_MOUSEMOTION) {
00231       mouse->hide();
00232       mouse->move(event.motion.x / scale, 
00233           event.motion.y / scale);
00234       set_selection(event.motion.x / scale, 
00235           event.motion.y / scale); 
00236       mouse->show();
00237       mouse->blit_dirty();
00238     } else if(event.type==SDL_MOUSEBUTTONDOWN) {
00239             if (!mouse_visible) {
00240               // if invisible, redraw mouse
00241               set_selection(event.button.x / scale, 
00242                 event.button.y / scale); 
00243               mouse->show();
00244               mouse->blit_dirty();
00245       }
00246     } else if(event.type==SDL_MOUSEBUTTONUP) {
00247             MenuObject *entry = (*entries)[selection];
00248       if (entry->is_mouse_over(
00249              event.button.x / scale, 
00250              event.button.y / scale)) {
00251               exit_loop = entry->handle_event(event);
00252       }
00253     } else if(event.type==SDL_KEYDOWN) {
00254       mouse->hide();
00255       mouse->blit_dirty();
00256       switch(event.key.keysym.sym) {
00257       case SDLK_x:
00258         if(event.key.keysym.mod & KMOD_ALT) {
00259           return -1;
00260         }
00261         break;
00262 #if defined(MACOS) || defined(MACOSX)
00263       case SDLK_q:
00264         if(event.key.keysym.mod & KMOD_META) {
00265           return -1;
00266         }
00267         break;
00268 #endif
00269       case SDLK_UP:
00270         if (!selected)
00271         {
00272           // if unselected (by 'MouseOut' event), just re-select
00273           set_selection(selection);
00274           continue;
00275         }
00276         if(selection<=0)
00277           set_selection(count-1);
00278         else
00279           set_selection(selection-1);
00280         continue;
00281       case SDLK_DOWN:
00282         if (!selected)
00283         {
00284           // if unselected (by 'MouseOut' event), just re-select
00285           set_selection(selection);
00286           continue;
00287         }
00288         if(selection>=(count-1))
00289           set_selection(0);
00290         else
00291           set_selection(selection+1);
00292         continue;
00293       case SDLK_s:
00294         if ((event.key.keysym.mod & KMOD_ALT) &&
00295             (event.key.keysym.mod & KMOD_CTRL))
00296           make_screenshot(true);
00297       default:
00298         {
00299                 // let key be processed by selected menu-item
00300           if(selected) {
00301             MenuObject *entry = (*entries)[selection];
00302             exit_loop = entry->handle_event(event);
00303           }
00304         }
00305         break;
00306       }
00307     } else if(event.type==SDL_QUIT) {
00308                         return -1;
00309     }
00310   } while(!exit_loop);
00311   mouse->hide();
00312   return selection;
00313 }
00314 

Generated on Mon Jul 9 14:42:48 2007 for ExultEngine by  doxygen 1.5.1