menu.h

00001 // menu.h  -*-c++-*-
00002 //
00003 //   Copyright (C) 2000-2005 Daniel Burrows
00004 //
00005 //   This program is free software; you can redistribute it and/or
00006 //   modify it under the terms of the GNU General Public License as
00007 //   published by the Free Software Foundation; either version 2 of
00008 //   the License, or (at your option) any later version.
00009 //
00010 //   This program is distributed in the hope that it will be useful,
00011 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 //   General Public License for more details.
00014 //
00015 //   You should have received a copy of the GNU General Public License
00016 //   along with this program; see the file COPYING.  If not, write to
00017 //   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018 //   Boston, MA 02111-1307, USA.
00019 //
00020 //  A nice menu with selectable entries.  (fairly basic atm)
00021 
00022 #ifndef MENU_H
00023 #define MENU_H
00024 
00025 #include "widget.h"
00026 
00027 #include <cwidget/config/keybindings.h>
00028 
00029 #include <cwidget/generic/util/bool_accumulate.h>
00030 #include <cwidget/generic/util/slotarg.h>
00031 
00032 #include <vector>
00033 
00034 namespace cwidget
00035 {
00036   namespace widgets
00037   {
00038     // Currently, menu-items aren't full widgets--it's simply too much
00039     // baggage (lots of signals and a Curses window) for something that's
00040     // quite simple and special-purpose.
00041     class menu_item
00042     {
00043       // The text displayed in the menu entry
00044       std::wstring title;
00045 
00046       // A string describing the item's function
00047       std::wstring description;
00048 
00049       // The keybinding whose definition (in the GLOBAL bindings list) is
00050       // displayed to the right of the menu entry.
00051       std::string binding;
00052 
00053       // The key that directly activates this item *while the menu is open*
00054       chtype hotkey;
00055     public:
00056       // Infers the hotkey from the title
00057       menu_item(const std::wstring &_title, const std::string &_binding,
00058                 const std::wstring &_description);
00059 
00060       std::wstring get_title() const {return title;}
00061       std::string get_binding() const {return binding;}
00062       std::wstring get_description() const {return description;}
00063       chtype get_hotkey() const {return hotkey;}
00064 
00066       bool is_enabled() const;
00067 
00069       sigc::signal0<void> selected;
00070 
00077       sigc::signal0<bool, util::accumulate_or> enabled;
00078     };
00079 
00080 #define MENU_NOP NULL
00081 
00082     // Info for easy static generation of menus
00083 
00084     struct menu_info
00085     {
00086     public:
00087       // MENU_ITEM: a "real" menu-item
00088       // MENU_END: the last item in this information block
00089       enum item_types {MENU_ITEM, MENU_SEPARATOR, MENU_END} item_type;
00090 
00092       const char *item_name, *item_binding, *item_description;
00093 
00094       // How to communicate with the outside world..
00095       util::slot0arg item_slot;
00096 
00097       // For activation
00098       util::slotarg<sigc::slot0<bool> >  item_enabled;
00099 
00100       menu_info(item_types type, const char *name, const char *binding,
00101                 const char *description, sigc::slot0<void> slot);
00102 
00103       menu_info(item_types type, const char *name, const char *binding,
00104                 const char *description, sigc::slot0<void> *slot);
00105 
00106       menu_info(item_types type, const char *name, const char *binding,
00107                 const char *description, sigc::slot0<void> slot,
00108                 sigc::slot0<bool> enabled);
00109 
00110       menu_info(item_types type, const char *name, const char *binding,
00111                 const char *description, sigc::slot0<void> *slot,
00112                 sigc::slot0<bool> enabled);
00113 
00114       menu_info(item_types type);
00115     };
00116 
00117     const menu_info MENU_SEPARATOR(menu_info::MENU_SEPARATOR);
00118     const menu_info MENU_END(menu_info::MENU_END);
00119 
00120     class menu : public widget
00121     {
00122       typedef std::vector<menu_item *> itemlist;
00123 
00124       // A set of menu items.  NULL indicates a separator.
00125       // These items are deleted with the menu.
00126       itemlist items;
00127 
00129       itemlist::size_type cursorloc;
00130 
00132       itemlist::size_type startloc;
00133 
00135       int min_width;
00136 
00137       // connected to "shown"
00138       void appear();
00139 
00140       // connected to "hidden"
00141       void disappear();
00142 
00146       void update_startloc();
00147 
00149       bool selectable(itemlist::size_type pos);
00150 
00152       void set_cursor(itemlist::size_type pos);
00153 
00157       void highlight_current();
00158 
00165       itemlist::size_type next_selectable(itemlist::size_type pos);
00166 
00174       itemlist::size_type prev_selectable(itemlist::size_type pos);
00175 
00182       void sanitize_cursor(bool forward);
00183 
00184     protected:
00185       virtual bool handle_key(const config::key &k);
00186 
00188       menu();
00189 
00190       // Initialize a menu from a block of information.  If there is no
00191       // MENU_END in the block, RANDOM ERRORS WILL OCCUR!!
00192       menu(int x, int y, int w, menu_info *inf);
00193     public:
00194       static util::ref_ptr<menu> create()
00195       {
00196         util::ref_ptr<menu> rval(new menu);
00197         rval->decref();
00198         return rval;
00199       }
00200 
00201       static util::ref_ptr<menu> create(int x, int y, int w, menu_info *inf)
00202       {
00203         util::ref_ptr<menu> rval(new menu(x, y, w, inf));
00204         rval->decref();
00205         return rval;
00206       }
00207 
00208       // Deletes the items it holds!
00209       ~menu();
00210 
00211       bool get_cursorvisible();
00212       point get_cursorloc();
00213 
00214       int width_request();
00215       int height_request(int width);
00216 
00217       void append_item(menu_item *newitem);
00218       void remove_item(menu_item *item);
00219 
00221       void move_selection_up();
00222 
00224       void move_selection_down();
00225 
00227       void move_selection_top();
00228 
00230       void move_selection_bottom();
00231 
00232       virtual bool focus_me();
00233       virtual void paint(const style &st);
00234       virtual void dispatch_mouse(short id, int x, int y, int z, mmask_t bstate);
00235 
00236       // Emitted when an item is highlighted or when the selection "goes away".
00237       // In the latter case, the argument is NULL.  (happens only when
00238       // the menu is hidden -- FIXME?)
00239       sigc::signal1<void, menu_item *> item_highlighted;
00240 
00241       // FIXME: there should be a less hacky way..
00242       sigc::signal0<void> menus_goaway;
00243 
00244       static config::keybindings *bindings;
00245       static void init_bindings();
00246     };
00247 
00248     typedef util::ref_ptr<menu> menu_ref;
00249   }
00250 }
00251 
00252 #endif

Generated on Sat Jun 12 14:51:02 2010 for cwidget by  doxygen 1.5.6