cwidget
0.5.16
|
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