1 // * This makes emacs happy -*-Mode: C++;-*-
2 /*-----------------------------------------------------------------------------+
3 | The ncurses menu C++ binding is Copyright (C) 1997 |
4 | by Juergen Pfeifer <Juergen.Pfeifer@T-Online.de> |
5 | All Rights Reserved. |
7 | Permission to use, copy, modify, and distribute this software and its |
8 | documentation for any purpose and without fee is hereby granted, provided |
9 | that the above copyright notice appear in all copies and that both that |
10 | copyright notice and this permission notice appear in supporting |
11 | documentation, and that the name of the above listed copyright holder(s) not |
12 | be used in advertising or publicity pertaining to distribution of the |
13 | software without specific, written prior permission. |
15 | THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD TO |
16 | THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- |
17 | NESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR |
18 | ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RE- |
19 | SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
20 | NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH |
21 | THE USE OR PERFORMANCE OF THIS SOFTWARE. |
22 +-----------------------------------------------------------------------------*/
34 // This wraps the ITEM type of <menu.h>
37 friend class NCursesMenu;
42 void OnError (int err) const THROWS(NCursesMenuException)
45 THROW(new NCursesMenuException (err));
49 // Create an item. If you pass both parameters as NULL, a delimiter
50 // item is constructed which can be used to terminate a list of
51 // NCursesMenu objects.
52 NCursesMenuItem (const char* p_name = NULL,
53 const char* p_descript = NULL )
55 item = p_name ? ::new_item (p_name, p_descript) : (ITEM*)0;
57 OnError (E_SYSTEM_ERROR);
60 // Release the items memory
61 virtual ~NCursesMenuItem ()
68 inline const char* name () const
70 return ::item_name (item);
73 // Description of the item
74 inline const char* description () const
76 return ::item_description (item);
79 // index of the item in an item array (or -1)
80 inline int index (void) const
82 return ::item_index (item);
85 // switch on an item's option
86 inline void options_on (Item_Options options)
88 OnError (::item_opts_on (item, options));
91 // switch off an item's option
92 inline void options_off (Item_Options options)
94 OnError (::item_opts_off (item, options));
97 // return the item's options
98 inline Item_Options options () const
100 return ::item_opts (item);
103 // set the item's options
104 inline void set_options (Item_Options options)
106 OnError (::set_item_opts (item, options));
109 // set/reset the item's selection state
110 inline void set_value (bool f)
112 OnError (::set_item_value (item,f));
115 // return the item's selection state
116 inline bool value () const
118 return ::item_value (item);
121 // return visibility of the item
122 inline bool visible () const
124 return ::item_visible (item);
127 // perform an action associated with this item; you may use this in an
128 // user supplied driver for a menu; you may derive from this class and
129 // overload action() to supply items with different actions.
130 // If an action returns true, the menu will be exited.
131 virtual bool action() {
136 // Prototype for an items callback function.
137 typedef bool ITEMCALLBACK(NCursesMenuItem&);
139 // If you don't like to create a child class for individual items to
140 // overload action(), you may use this class and provide a callback
141 // function pointer for items.
142 class NCursesMenuCallbackItem : public NCursesMenuItem
145 const ITEMCALLBACK* p_fct;
148 NCursesMenuCallbackItem(const ITEMCALLBACK* fct = NULL,
149 const char* p_name = NULL,
150 const char* p_descript = NULL )
151 : NCursesMenuItem (p_name, p_descript),
155 virtual ~NCursesMenuCallbackItem() {
160 return p_fct (*this);
167 class NCursesMenu : public NCursesPanel {
172 // Keep book of the number of instantiated C++ menus.
173 static unsigned long total_count;
175 NCursesWindow* sub; // the subwindow object
176 bool b_sub_owner; // is this our own subwindow?
177 bool b_framed; // has the menu a border?
179 NCursesMenuItem** my_items; // The array of items for this menu
181 // This structure is used for the menu's user data field to link the
182 // MENU* to the C++ object and to provide extra space for a user pointer.
184 const void* m_user; // the pointer for the user's data
185 const NCursesMenu* m_back; // backward pointer to C++ object
189 // Get the backward pointer to the C++ object from a MENU
190 static inline NCursesMenu* getHook(const MENU *m)
192 UserHook* hook = (UserHook*)::menu_userptr(m);
193 assert(hook && hook->m_owner==m);
194 return (NCursesMenu*)(hook->m_back);
197 // This are the built-in hook functions in this C++ binding. In C++ we use
198 // virtual member functions (see below On_..._Init and On_..._Termination)
199 // to provide this functionality in an object oriented manner.
200 static void mnu_init(MENU *);
201 static void mnu_term(MENU *);
202 static void itm_init(MENU *);
203 static void itm_term(MENU *);
205 // Calculate ITEM* array for the menu
206 ITEM** mapItems(NCursesMenuItem* nitems[]);
210 void set_user(const void *user)
212 UserHook* uptr = (UserHook*)::menu_userptr (menu);
213 assert (uptr && uptr->m_back==this && uptr->m_owner==menu);
217 const void *get_user()
219 UserHook* uptr = (UserHook*)::menu_userptr (menu);
220 assert (uptr && uptr->m_back==this && uptr->m_owner==menu);
225 void InitMenu (NCursesMenuItem* menu[], bool with_frame=FALSE);
227 void OnError (int err) const THROWS(NCursesMenuException)
230 THROW(new NCursesMenuException (this, err));
233 // this wraps the menu_driver call.
234 virtual int driver (int c) ;
237 // make a full window size menu
238 NCursesMenu (NCursesMenuItem* menu[]);
240 // make a menu with a window of this size.
241 NCursesMenu (NCursesMenuItem* menu[],
246 bool with_frame=FALSE);
248 virtual ~NCursesMenu ();
250 // Retrieve the menus subwindow
251 inline NCursesWindow& subWindow() const {
256 // Set the menus subwindow
257 void setSubWindow(NCursesWindow& sub);
259 // Set these items for the menu
260 void setItems(NCursesMenuItem* nitems[]);
262 // Remove the menu from the screen
263 inline void unpost (void)
265 OnError (::unpost_menu (menu));
268 // Post the menu to the screen if flag is true, unpost it otherwise
269 inline void post(bool flag = TRUE)
271 flag ? OnError (::post_menu(menu)) : OnError (::unpost_menu (menu));
274 // Get the numer of rows and columns for this menu
275 inline void scale (int& mrows, int& mcols) const
277 OnError (::scale_menu (menu, &mrows, &mcols));
280 // Set the format of this menu
281 inline void set_format(int mrows, int mcols)
283 OnError (::set_menu_format(menu, mrows, mcols));
286 // Get the format of this menu
287 void menu_format(int& rows,int& cols)
289 ::menu_format(menu,&rows,&cols);
293 NCursesMenuItem* items() const
298 // Get the number of items in this menu
301 return ::item_count(menu);
304 // Get the current item (i.e. the one the cursor is located)
305 NCursesMenuItem& current_item() const
307 return *(my_items[::item_index(::current_item(menu))]);
310 // Get the marker string
311 inline const char* mark() const
313 return ::menu_mark(menu);
316 // Set the marker string
317 inline void set_mark(const char *mark)
319 OnError (::set_menu_mark (menu, mark));
322 // Get the name of the request code c
323 inline static const char* request_name(int c)
325 return ::menu_request_name(c);
328 // Get the current pattern
329 inline char* pattern() const
331 return ::menu_pattern(menu);
334 // true if there is a pattern match, false otherwise.
335 bool set_pattern (const char *pat);
337 // set the default attributes for the menu
338 // i.e. set fore, back and grey attribute
339 virtual void setDefaultAttributes();
341 // Get the menus background attributes
344 return ::menu_back(menu);
347 // Get the menus foreground attributes
350 return ::menu_fore(menu);
353 // Get the menus grey attributes (used for unselectable items)
356 return ::menu_grey(menu);
359 // Set the menus background attributes
360 chtype set_background(chtype a)
362 return ::set_menu_back(menu,a);
365 // Set the menus foreground attributes
366 chtype foreground(chtype a)
368 return ::set_menu_fore(menu,a);
371 // Set the menus grey attributes (used for unselectable items)
372 chtype set_grey(chtype a)
374 return ::set_menu_grey(menu,a);
377 inline void options_on (Menu_Options opts)
379 OnError (::menu_opts_on (menu,opts));
382 inline void options_off(Menu_Options opts)
384 OnError (::menu_opts_off(menu,opts));
387 inline Menu_Options options() const {
388 return ::menu_opts(menu);
391 inline void set_options (Menu_Options opts)
393 OnError (::set_menu_opts (menu,opts));
396 inline int pad() const
398 return ::menu_pad(menu);
401 inline void set_pad (int padch)
403 OnError (::set_menu_pad (menu, padch));
406 // Position the cursor to the current item
407 inline void position_cursor () const
409 OnError (::pos_menu_cursor (menu));
412 // Set the current item
413 inline void set_current(NCursesMenuItem& I)
415 OnError (::set_current_item(menu, I.item));
418 // Get the current top row of the menu
419 inline int top_row (void) const
421 return ::top_row (menu);
424 // Set the current top row of the menu
425 inline void set_top_row (int row)
427 OnError (::set_top_row (menu, row));
431 // Set the spacing for the menu
432 inline void setSpacing(int spc_description,
435 OnError(::set_menu_spacing(menu,
441 // Get the spacing info for the menu
442 inline void Spacing(int& spc_description,
444 int& spc_columns) const {
445 OnError(::menu_spacing(menu,
452 void frame(const char *title=NULL, const char* btitle=NULL) {
454 NCursesPanel::frame(title,btitle);
456 OnError(E_SYSTEM_ERROR);
459 void boldframe(const char *title=NULL, const char* btitle=NULL) {
461 NCursesPanel::boldframe(title,btitle);
463 OnError(E_SYSTEM_ERROR);
466 void label(const char *topLabel, const char *bottomLabel) {
468 NCursesPanel::label(topLabel,bottomLabel);
470 OnError(E_SYSTEM_ERROR);
477 // Called after the menu gets repositioned in its window.
478 // This is especially true if the menu is posted.
479 virtual void On_Menu_Init()
483 // Called before the menu gets repositioned in its window.
484 // This is especially true if the menu is unposted.
485 virtual void On_Menu_Termination()
489 // Called after the item became the current item
490 virtual void On_Item_Init(NCursesMenuItem& item)
494 // Called before this item is left as current item.
495 virtual void On_Item_Termination(NCursesMenuItem& item)
499 // Provide a default key virtualization. Translate the keyboard
500 // code c into a menu request code.
501 // The default implementation provides a hopefully straightforward
502 // mapping for the most common keystrokes and menu requests.
503 virtual int virtualize(int c);
507 NCursesMenuItem& operator[](int i) const
509 if ( (i < 0) || (i >= ::item_count (menu)) )
510 OnError (E_BAD_ARGUMENT);
511 return *(my_items[i]);
514 // Perform the menu's operation
515 // Return the item where you left the selection mark.
516 virtual NCursesMenuItem& operator()(void);
518 // --------------------
519 // Exception handlers
520 // Called by operator()
521 // --------------------
523 // Called if the request is denied
524 virtual void On_Request_Denied(int c) const {
528 // Called if the item is not selectable
529 virtual void On_Not_Selectable(int c) const {
533 // Called if pattern doesn't match
534 virtual void On_No_Match(int c) const {
538 // Called if the command is unknown
539 virtual void On_Unknown_Command(int c) const {
545 // This is the typical C++ typesafe way to allow to attach
546 // user data to an item of a menu. Its assumed that the user
547 // data belongs to some class T. Use T as template argument
548 // to create a UserItem.
549 template<class T> class NCursesUserItem : public NCursesMenuItem
552 NCursesUserItem (const char* p_name = NULL,
553 const char* p_descript = NULL )
554 : NCursesMenuItem (p_name, p_descript)
557 NCursesUserItem (const T* p_UserData,
559 const char* p_descript = NULL )
560 : NCursesMenuItem (p_name, p_descript)
563 OnError (::set_item_userptr (item, (const void *)p_UserData));
566 virtual ~NCursesUserItem() {};
568 const T* UserData (void) const
570 return (const T*)::item_userptr (item);
573 virtual void setUserData(const T* p_UserData) {
575 OnError (::set_item_userptr (item, (const void *)p_UserData));
579 // The same mechanism is used to attach user data to a menu
580 template<class T> class NCursesUserMenu : public NCursesMenu
583 NCursesUserMenu (NCursesMenuItem menu[])
587 NCursesUserMenu (const T* p_UserData,
588 NCursesMenuItem menu[])
592 set_user ((const void *)p_UserData);
595 NCursesUserMenu (const T* p_UserData,
596 NCursesMenuItem menu[],
601 bool with_frame=FALSE)
602 : NCursesMenu (menu, lines, cols, begin_y, begin_x, with_frame)
605 set_user ((const void *)p_UserData);
608 virtual ~NCursesUserMenu() {};
610 const T* UserData (void) const
612 return (const T*)get_user ();
615 virtual void setUserData (const T* p_UserData) {
617 set_user ((const void *)p_UserData);