/[enigma]/enigma/src/menus.cc
ViewVC logotype

Diff of /enigma/src/menus.cc

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.63 by dheck, Fri Sep 12 21:49:45 2003 UTC revision 1.64 by dheck, Sun Sep 14 19:32:35 2003 UTC
# Line 39  using namespace px; Line 39  using namespace px;
39  using namespace OxydLib;  using namespace OxydLib;
40    
41    
42  //----------------------------------------------------------------------  #include "menus_internal.hh"
 // Helper classes  
 //----------------------------------------------------------------------  
 namespace  
 {  
     class BuildVList {  
         Rect r;  
         Menu *container;  
         int skip;  
     public:  
         BuildVList(Menu *cc, const px::Rect &rr, int s)  
             : r(rr), container(cc), skip(s)  
         {}  
   
         Widget *add(Widget *w) {  
             container->add(w, r);  
             r.y += r.h+skip;  
             return w;  
         }  
   
         Rect pos() const { return r; }  
     };  
   
     class VTableBuilder {  
         Menu             *m_menu;  
         px::Rect          m_widgetsize;  
         int               m_hspacing, m_vspacing;  
         vector<Widget *>  m_widgets;  
         int               m_maxheight;  
     public:  
         VTableBuilder (Menu *menu, const px::Rect &widgetsize,  
                        int vspacing, int hspacing, int max_height)  
         : m_menu(menu), m_widgetsize(widgetsize)  
         {  
             m_hspacing = hspacing;  
             m_vspacing = vspacing;  
             m_maxheight = max_height;  
         }  
           
         Widget *add (Widget *w) {  
             m_widgets.push_back(w);  
             return w;  
         }  
   
         void finish() {  
             if (m_widgets.empty())  
                 return;  
             int ncolumns = m_widgets.size() / m_maxheight;  
             int nrows = (m_widgets.size() + ncolumns - 1) / ncolumns;  
             int i=0;  
             int x=0;  
             for (int col = 0; col < ncolumns; col++) {  
                 int y=0;  
                 for (int row=0; row < nrows; row++, i++) {  
                     if (i == (int)m_widgets.size())  
                         goto done;  
                     px::Rect rr(x, y, m_widgetsize.w, m_widgetsize.h);  
                     m_menu->add(m_widgets[i], rr);  
 //                    m_widgets[i]->move (x, y);  
                     y += m_widgetsize.h + m_vspacing;  
                 }  
                 x += m_widgetsize.w + m_hspacing;  
             }  
           done:  
             return;  
         }  
     };  
   
     class BuildHList {  
         Rect r;  
         Menu *container;  
         int skip;  
     public:  
         BuildHList(Menu *cc, const px::Rect &rr, int s)  
         : r(rr), container(cc), skip(s)  
         {}  
   
         Widget * add(Widget *w) {  
             container->add(w, r);  
             r.x += r.w+skip;  
             return w;  
         }  
         Widget *add (Widget *w, int width) {  
             px::Rect rr(r.x, r.y, width, r.h);  
             container->add(w, rr);  
             r.x += width + skip;  
             return w;  
         }  
   
         Rect pos() const { return r; }  
     };  
 }  
   
 namespace  
 {  
   
     class ImageAlloc {  
     public:  
         px::Surface *acquire(const std::string &name) {  
             return px::LoadImage(name.c_str());  
         }  
         void release(px::Surface *s) { delete s; }  
     };  
   
     typedef Cache<px::Surface*, ImageAlloc> ImageCache;  
   
   
     class LevelPreviewCacheElem {  
         Surface *surface;  
         unsigned idx;  
   
         LevelPreviewCacheElem(const LevelPreviewCacheElem&);  
         LevelPreviewCacheElem& operator = (const LevelPreviewCacheElem& other);  
     public:  
         LevelPreviewCacheElem(LevelPack *lp, unsigned idx_, int xsize, int ysize)  
         : surface(0) , idx(idx_)  
         {  
             surface = LevelPreview(lp, idx); // do not free, points to BackBuffer  
             if (surface) {  
                 const Rect&  game_area    = display::GetGameArea();  
                 Surface     *game_surface = Grab(surface, game_area);  
   
                 if (game_surface) {  
                     surface = game_surface->zoom(xsize, ysize);  
                     delete game_surface;  
                 }  
                 else {  
                     surface = 0; // avoid delete  
                 }  
             }  
   
             // fprintf(stderr, "Created preview for #%i. surface=%p\n", idx, surface);  
         }  
         ~LevelPreviewCacheElem() { delete surface; }  
         bool operator<(const LevelPreviewCacheElem& other) { return idx<other.idx; }  
         Surface *get_surface() { return surface; }  
     };  
   
     class LevelPreviewCache {  
         typedef std::map<unsigned,LevelPreviewCacheElem*> PreviewMap;  
   
         PreviewMap cache;  
         int        xsize, ysize;  
   
         void release() {  
             PreviewMap::iterator i = cache.begin();  
             PreviewMap::iterator e = cache.end();  
             for (; i != e; ++i)  
                 delete i->second;  
         }  
   
     public:  
         LevelPreviewCache() : xsize(0), ysize(0) {}  
         ~LevelPreviewCache() { release(); }  
   
         void clear() { release(); cache.clear(); }  
         void set_size(int xs, int ys) { xsize = xs; ysize = ys; }  
   
         Surface *getPreview(LevelPack *lp, unsigned idx) {  
             PreviewMap::iterator i = cache.find(idx);  
             if (i != cache.end())  
                 return i->second->get_surface();  
   
             assert(xsize != 0 && ysize != 0); // forgot to call set_size() ?  
             LevelPreviewCacheElem *ce = new LevelPreviewCacheElem(lp, idx, xsize, ysize);  
   
             Surface *surface = ce->get_surface();  
             if (!surface)   delete ce; // dont add broken levels to cache  
             else            cache[idx] = ce;  
   
             return surface;  
         }  
     };  
   
   
     class LevelPackMenu : public Menu {  
     public:  
         LevelPackMenu();  
   
         void on_action(Widget *w);  
         void draw_background(px::GC &gc);  
         int get_selection() const { return m_selection; }  
   
     private:  
         vector<Widget *> buttons;  
         int m_selection;  
     };  
   
   
     class LevelMenu;  
   
     class LevelWidget : public Widget {  
     public:  
         LevelWidget(LevelPack *lp, int w, int h);  
         bool manage ();  
         int selected_level() const { return iselected; }  
   
         // Widget interface.  
         void draw(px::GC &gc, const px::Rect &r);  
   
         void set_listener(ActionListener *al) {  
             listener = al;  
         }  
         void trigger_action() {  
   
             cache.clear();  
             if (listener) {  
                 listener->on_action(this);  
                 recalc_available();  
             }  
         }  
   
         void change_levelpack (LevelPack *lp);  
   
         void page_up();  
         void page_down();  
         void start() { set_selected (0,0); }  
         void end() { set_current(level_pack->size()-1); }  
   
         void set_current(int newsel) { set_selected(ifirst, newsel); }  
         void next_unsolved();  
   
         bool on_event(const SDL_Event &e);  
   
         LevelMenu *get_menu();  
   
         int get_position() const {  
             return (ifirst << 4) | (iselected-ifirst);  
         }  
         void set_position(int pos) {  
             int new_first = pos >> 4;  
             int off       = pos&0xf;  
             int new_sel   = new_first+off;  
             assert(off >= 0 && off < 12); // 12 levels per page  
             set_selected(new_first, new_sel);  
         }  
   
         void show_text(const string& text);  
   
     private:  
         // Private functions.  
         void scroll_up(int lines);  
         void scroll_down(int lines);  
         void set_selected (int newfirst, int newsel);  
         void recalc_available ();  
   
         // Event handling.  
         bool handle_keydown (const SDL_Event *e);  
         bool handle_mousedown (const SDL_Event *e);  
   
         /*  
         ** Variables.  
         */  
         ImageCache         cache;  
         LevelPack         *level_pack; // The current level pack  
         LevelPreviewCache  preview_cache;  
   
         int               ifirst; // Index of "upper left" level  
         int               iselected; // Index of selected level  
         int               max_available; // Index of the last available level (one can choose out of x unsolved levels)  
         int               width, height;  
         vector<px::Rect>  m_areas; // Screen areas occupied by level previews  
         ActionListener   *listener;  
     };  
   
     class LevelMenu : public Menu {  
     public:  
         LevelMenu(LevelPack *lp, unsigned long pos);  
   
         // rotate through levelpacks  
         void next_levelpack() {  
             unsigned next_pack = m_ilevelpack+1;  
             if (next_pack == enigma::LevelPacks.size()) next_pack = 0;  
             set_levelpack(next_pack);  
         }  
         void previous_levelpack() {  
             unsigned prev_pack = m_ilevelpack;  
             if (prev_pack == 0) prev_pack = enigma::LevelPacks.size()-1;  
             else --prev_pack;  
             set_levelpack(prev_pack);  
         }  
   
         int get_position() const {  
             return (m_ilevelpack << 16) | (levelwidget->get_position() & 0xffff);  
         }  
         void set_position(int pos) {  
             set_levelpack(pos >> 16);  
             levelwidget->set_position(pos & 0xffff);  
         }  
   
         void show_text(const string& text) {  
             shown_text     = text;  
             shown_text_ttl = 2.0; // show for two seconds  
         }  
   
     private:  
   
         void update_info();  
   
         void set_levelpack (unsigned index);  
   
         // Menu interface.  
         void tick (double time);  
         void draw_background(px::GC &gc);  
   
         // Widget interface.  
         bool on_event (const SDL_Event &e);  
   
         // ActionListener interface.  
         void on_action(Widget *w);  
   
         // Variables.  
   
         Widget *pgup, *pgdown, *start, *end, *unsolved;  
   
         Widget      *newgame;  
         Widget      *back;  
         Widget      *m_nextlp, *m_prevlp; // Next/previous level pack  
         TextButton  *m_lpbutton; // Current level pack  
         Label       *m_infobutton;  
         Label       *m_levelinfo, *m_levelinfo2;  
         LevelWidget *levelwidget;  
         LevelPack   *level_pack;  
         unsigned     m_ilevelpack;  
         string       shown_text; // info text (disappears automatically)  
         double       shown_text_ttl; // rest duration for shown_text  
     };  
   
     class MainMenu : public Menu {  
     public:  
         MainMenu();  
     private:  
         // Menu interface  
         void draw_background(px::GC &gc);  
   
         // ActionListener interface.  
         void on_action(Widget *w);  
   
         // Private methods.  
         void show_credits();  
         void show_help();  
         void show_text( const char *text[]);  
   
         // Variables.  
         Widget *m_startgame;  
         Widget *leveled;  
         Widget *manual;  
         Widget *options;  
         Widget *credits;  
         Widget *quit;  
         Widget *lpack;  
     };  
 }  
   
43    
44  //----------------------------------------------------------------------  //----------------------------------------------------------------------
45  // Level pack menu  // Level pack menu
# Line 797  LevelWidget::handle_keydown (const SDL_E Line 444  LevelWidget::handle_keydown (const SDL_E
444  }  }
445    
446    
447  // ---------------------------------------------  //----------------------------------------
448  //      Button representing an integer value  // ValueButton implementation
449  // ---------------------------------------------  //----------------------------------------
450  namespace  
451    bool
452    ValueButton::update_value(int old_value, int new_value)
453    {
454        if (new_value<min_value) new_value      = min_value;
455        else if (new_value>max_value) new_value = max_value;
456    
457        if (new_value != old_value) {
458            set_value(new_value);
459            set_text(build_text(new_value));
460            return true;
461        }
462        return false;
463    }
464    
465    bool
466    ValueButton::on_event(const SDL_Event &e)
467  {  {
468      class ValueButton: public TextButton {      // handles button movement and
469          int min_value;      bool handled = PushButton::on_event(e);
         int max_value;  
470    
471          bool update_value(int old_value, int new_value);      switch (e.type) {
472        case SDL_KEYDOWN:
473            bool keyhandled   = true;
474            bool changed = false;
475    
476      public:          switch (e.key.keysym.sym) {
477          ValueButton(const std::string &t, int min_value_, int max_value_)          case SDLK_LEFT:  changed = inc_value(-1); break;
478              : TextButton(t, this)          case SDLK_RIGHT: changed = inc_value(1); break;
479              , min_value(min_value_)          default :
480              , max_value(max_value_)              keyhandled = false;
481          {}              break;
   
         virtual int get_value() const              = 0;  
         virtual void set_value(int value)          = 0;  
         virtual string build_text(int value) const = 0;  
   
         bool inc_value(int offset) {  
             int old_value = get_value();  
             return update_value(old_value, old_value+offset);  
         }  
         void update() {  
             update_value(-1, get_value());  
482          }          }
483    
484          // Widget interface          if (keyhandled) {
485          virtual bool on_event(const SDL_Event &e);              handled = true;
486          virtual void on_action(Widget *w);              sound::PlaySound(changed ? "menuswitch" : "menustop");
     };  
   
     bool ValueButton::update_value(int old_value, int new_value) {  
         if (new_value<min_value) new_value      = min_value;  
         else if (new_value>max_value) new_value = max_value;  
   
         if (new_value != old_value) {  
             set_value(new_value);  
             set_text(build_text(new_value));  
             return true;  
         }  
         return false;  
     }  
   
     bool ValueButton::on_event(const SDL_Event &e) {  
         // handles button movement and  
         bool handled = PushButton::on_event(e);  
   
         switch (e.type) {  
             case SDL_KEYDOWN:  
                 bool keyhandled   = true;  
                 bool changed = false;  
   
                 switch (e.key.keysym.sym) {  
                     case SDLK_LEFT:  
                         changed    = inc_value(-1);  
                         break;  
                     case SDLK_RIGHT:  
                         changed    = inc_value(1);  
                         break;  
                     default :  
                         keyhandled = false;  
                         break;  
                 }  
   
                 if (keyhandled) {  
                     handled = true;  
                     sound::PlaySound(changed ? "menuswitch" : "menustop");  
                 }  
   
                 break;  
487          }          }
488    
489          return handled;          break;
490      }      }
491    
492      void ValueButton::on_action(Widget */*w*/) {      return handled;
493          if (!inc_value(1))  }
             update_value(get_value(), min_value);  
494    
495      }  void
496    ValueButton::on_action(Widget */*w*/)
497    {
498        if (!inc_value(1))
499            update_value(get_value(), min_value);
500  }  }
501    
502    
# Line 1134  OptionsMenu::OptionsMenu(px::Surface *ba Line 750  OptionsMenu::OptionsMenu(px::Surface *ba
750      right.add (new SoundVolumeButton);      right.add (new SoundVolumeButton);
751      right.add (new SoundSetButton);      right.add (new SoundSetButton);
752      right.add (new MusicVolumeButton);      right.add (new MusicVolumeButton);
753      right.add (new InGameMusicButton);  //    right.add (new InGameMusicButton);
754      right.add (new StereoButton);      right.add (new StereoButton);
755    
756      {      {
# Line 1422  MainMenu::MainMenu() Line 1038  MainMenu::MainMenu()
1038  {  {
1039      BuildVList b(this, Rect((640-150)/2,150,150,40), 5);      BuildVList b(this, Rect((640-150)/2,150,150,40), 5);
1040      m_startgame = b.add(new TextButton("Start Game", this));      m_startgame = b.add(new TextButton("Start Game", this));
1041      leveled     = b.add(new TextButton("Editor", this));  //    leveled     = b.add(new TextButton("Editor", this));
1042      manual      = b.add(new TextButton("Manual", this));      manual      = b.add(new TextButton("Manual", this));
1043      options     = b.add(new TextButton("Options", this));      options     = b.add(new TextButton("Options", this));
1044      credits     = b.add(new TextButton("Credits", this));      credits     = b.add(new TextButton("Credits", this));
# Line 1538  MainMenu::show_help () Line 1154  MainMenu::show_help ()
1154          "another. Just play the first levels in the \"Oxyd & Co\" group and you",          "another. Just play the first levels in the \"Oxyd & Co\" group and you",
1155          "will get the idea.",          "will get the idea.",
1156          "In some other levels, called \"meditation landscapes\" you have a",          "In some other levels, called \"meditation landscapes\" you have a",
1157          "somewhat different job: You control a couple of small white marbles",          "different job: You control a couple of small white marbles",
1158          "simultaneously and have to put each of them into a pit on the floor.",          "simultaneously and have to put each of them into a pit on the floor.",
1159          "",          "",
1160          "Moving around:",          "Moving around:",
# Line 1573  MainMenu::show_help () Line 1189  MainMenu::show_help ()
1189          0          0
1190      };      };
1191      static const char *screen3[] = {      static const char *screen3[] = {
1192          "Something about stones:",          "Stones:",
1193          "",          "",
1194          "Most of the time the stones are nothing more than walls.",          "Most stones  are nothing more than walls.",
1195          "Some special stones are movable when hit strong enought.",          "Many stones are movable when hit strong enough.",
1196          "The wooden stone will build new floor if moved into water, space or",          "The wooden stone will build new floor if moved into water, space or",
1197          "abyss.",          "abyss.",
1198          "Others can be destroyed using a hammer, dynamite or a laser.",          "Others can be destroyed using a hammer, dynamite or a laser.",
1199          "Doors can be opened using a switch or trigger hidden somewhere",          "Doors can be opened using a switch or trigger hidden somewhere",
1200          "around in the level.",          "around in the level.",
1201          "Some magic stones can be changed when hit using a magicwand.",          "Some magic stones can be changed when hit using a magic wand.",
1202          "And some depend on the color of your marble.",          "And some depend on the color of your marble.",
1203          "",          "",
1204          0          0

Legend:
Removed from v.1.63  
changed lines
  Added in v.1.64

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26