1 // Menu.hh for FbTk - Fluxbox Toolkit 2 // Copyright (c) 2001 - 2004 Henrik Kinnunen (fluxgen at fluxbox dot org) 3 // 4 // Basemenu.hh for Blackbox - an X11 Window manager 5 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net) 6 // 7 // Permission is hereby granted, free of charge, to any person obtaining a 8 // copy of this software and associated documentation files (the "Software"), 9 // to deal in the Software without restriction, including without limitation 10 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 // and/or sell copies of the Software, and to permit persons to whom the 12 // Software is furnished to do so, subject to the following conditions: 13 // 14 // The above copyright notice and this permission notice shall be included in 15 // all copies or substantial portions of the Software. 16 // 17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 // DEALINGS IN THE SOFTWARE. 24 25 // $Id: Menu.hh 3954 2005-04-26 01:41:55Z simonb $ 26 27 #ifndef FBTK_MENU_HH 28 #define FBTK_MENU_HH 29 30 #include <X11/Xlib.h> 31 #include <vector> 32 #include <string> 33 #include <memory> 34 35 #include "FbWindow.hh" 36 #include "EventHandler.hh" 37 #include "RefCount.hh" 38 #include "Command.hh" 39 #include "Observer.hh" 40 #include "FbPixmap.hh" 41 #include "MenuTheme.hh" 42 #include "Timer.hh" 43 44 namespace FbTk { 45 46 class MenuItem; 47 class ImageControl; 48 49 /// Base class for menus 50 class Menu: public FbTk::EventHandler, FbTk::FbWindowRenderer, protected FbTk::Observer { 51 public: 52 enum Alignment{ ALIGNDONTCARE = 1, ALIGNTOP, ALIGNBOTTOM }; 53 enum { RIGHT = 1, LEFT }; 54 55 /** 56 Bullet type 57 */ 58 enum { EMPTY = 0, SQUARE, TRIANGLE, DIAMOND }; 59 60 Menu(MenuTheme &tm, ImageControl &imgctrl); 61 virtual ~Menu(); 62 63 /** 64 @name manipulators 65 */ 66 //@{ 67 /// add a menu item with a label and a command 68 int insert(const char *label, RefCount<Command> &cmd, int pos=-1); 69 /// add empty menu item 70 int insert(const char *label, int pos=-1); 71 /// add submenu 72 int insert(const char *label, Menu *submenu, int pos= -1); 73 /// add menu item 74 int insert(MenuItem *item, int pos=-1); 75 /// remove an item 76 int remove(unsigned int item); 77 /// remove all items 78 void removeAll(); setInternalMenu(bool val=true)79 inline void setInternalMenu(bool val = true) { m_internal_menu = val; } setAlignment(Alignment a)80 inline void setAlignment(Alignment a) { m_alignment = a; } setTorn()81 inline void setTorn() { m_torn = true; } removeParent()82 inline void removeParent() { if (m_internal_menu) m_parent = 0; } 83 /// raise this window 84 virtual void raise(); 85 /// lower this window 86 virtual void lower(); 87 /// select next item 88 void nextItem(); 89 /// select previous item 90 void prevItem(); 91 void enterSubmenu(); 92 void enterParent(); 93 94 void disableTitle(); 95 void enableTitle(); 96 97 void setScreen(int x, int y, int w, int h); 98 99 /** 100 @name event handlers 101 */ 102 //@{ 103 void handleEvent(XEvent &event); 104 void buttonPressEvent(XButtonEvent &bp); 105 void buttonReleaseEvent(XButtonEvent &br); 106 void motionNotifyEvent(XMotionEvent &mn); 107 void enterNotifyEvent(XCrossingEvent &en); 108 void leaveNotifyEvent(XCrossingEvent &ce); 109 void exposeEvent(XExposeEvent &ee); 110 void keyPressEvent(XKeyEvent &ke); 111 //@} 112 /// get input focus 113 void grabInputFocus(); 114 virtual void reconfigure(); 115 /// set label string 116 void setLabel(const char *labelstr); 117 /// move menu to x,y 118 void move(int x, int y); 119 virtual void updateMenu(int active_index = -1); 120 void setItemSelected(unsigned int index, bool val); 121 void setItemEnabled(unsigned int index, bool val); setMinimumSublevels(int m)122 inline void setMinimumSublevels(int m) { menu.minsub = m; } 123 virtual void drawSubmenu(unsigned int index); 124 /// show menu 125 virtual void show(); 126 /// hide menu 127 virtual void hide(); 128 virtual void clearWindow(); setActiveIndex(int index)129 void setActiveIndex(int index) { m_active_index = index; } 130 /*@}*/ 131 132 /** 133 @name accessors 134 */ 135 //@{ activeIndex() const136 inline int activeIndex() const { return m_active_index; } isTorn() const137 inline bool isTorn() const { return m_torn; } isVisible() const138 inline bool isVisible() const { return m_visible; } screenNumber() const139 inline int screenNumber() const { return menu.window.screenNumber(); } window() const140 inline Window window() const { return menu.window.window(); } fbwindow()141 inline FbWindow &fbwindow() { return menu.window; } fbwindow() const142 inline const FbWindow &fbwindow() const { return menu.window; } titleWindow()143 inline FbWindow &titleWindow() { return menu.title; } frameWindow()144 inline FbWindow &frameWindow() { return menu.frame; } label() const145 inline const std::string &label() const { return menu.label; } x() const146 inline int x() const { return menu.window.x(); } y() const147 inline int y() const { return menu.window.y(); } width() const148 inline unsigned int width() const { return menu.window.width(); } height() const149 inline unsigned int height() const { return menu.window.height(); } numberOfItems() const150 inline unsigned int numberOfItems() const { return menuitems.size(); } currentSubmenu() const151 inline int currentSubmenu() const { return m_which_sub; } 152 bool hasSubmenu(unsigned int index) const; 153 bool isItemSelected(unsigned int index) const; 154 bool isItemEnabled(unsigned int index) const; 155 bool isItemSelectable(unsigned int index) const; theme() const156 inline const MenuTheme &theme() const { return m_theme; } alpha() const157 inline unsigned char alpha() const { return theme().alpha(); } focused()158 inline static Menu *focused() { return s_focused; } 159 /// @return menuitem at index find(unsigned int index) const160 inline const MenuItem *find(unsigned int index) const { return menuitems[index]; } find(unsigned int index)161 inline MenuItem *find(unsigned int index) { return menuitems[index]; } 162 //@} 163 /// @return true if index is valid validIndex(int index) const164 inline bool validIndex(int index) const { return (index < static_cast<int>(numberOfItems()) && index >= 0); } 165 parent()166 inline Menu *parent() { return m_parent; } parent() const167 inline const Menu *parent() const { return m_parent; } 168 169 void renderForeground(FbWindow &win, FbDrawable &drawable); 170 171 protected: 172 setTitleVisibility(bool b)173 inline void setTitleVisibility(bool b) { 174 m_title_vis = b; m_need_update = true; 175 if (!b) 176 titleWindow().lower(); 177 else 178 titleWindow().raise(); 179 } 180 itemSelected(int button,unsigned int index)181 virtual void itemSelected(int button, unsigned int index) { } 182 // renders item onto pm 183 int drawItem(FbDrawable &pm, unsigned int index, 184 bool highlight = false, 185 bool exclusive_drawable = false); 186 void clearItem(int index, bool clear = true); 187 void highlightItem(int index); 188 virtual void redrawTitle(FbDrawable &pm); 189 virtual void redrawFrame(FbDrawable &pm); 190 191 virtual void internal_hide(); 192 193 void update(FbTk::Subject *); 194 195 private: 196 197 void openSubmenu(); 198 void closeMenu(); 199 void startHide(); 200 void stopHide(); 201 202 203 typedef std::vector<MenuItem *> Menuitems; 204 MenuTheme &m_theme; 205 Menu *m_parent; 206 ImageControl &m_image_ctrl; 207 Menuitems menuitems; 208 209 int m_screen_x, m_screen_y; 210 int m_screen_width, m_screen_height; 211 bool m_moving; ///< if we're moving/draging or not 212 bool m_visible; ///< menu visibility 213 bool m_torn; ///< torn from parent 214 bool m_internal_menu; ///< whether we should destroy this menu or if it's managed somewhere else 215 bool m_title_vis; ///< title visibility 216 bool m_shifted; ///< if the menu is shifted to the other side of the parent 217 218 int m_which_sub, m_which_press, m_which_sbl; 219 Alignment m_alignment; 220 221 struct _menu { 222 Pixmap frame_pixmap, title_pixmap, hilite_pixmap; 223 FbTk::FbWindow window, frame, title; 224 225 std::string label; 226 int x_move, y_move, x_shift, y_shift, sublevels, persub, minsub, 227 grab_x, grab_y; 228 229 unsigned int frame_h, item_w; 230 } menu; 231 232 int m_active_index; ///< current highlighted index 233 234 Drawable m_root_pm; 235 static Menu *s_focused; ///< holds current input focused menu, so one can determine if a menu is focused 236 bool m_need_update; 237 Timer m_submenu_timer; 238 Timer m_hide_timer; 239 }; 240 241 } // end namespace FbTk 242 243 #endif // FBTK_MENU_HH 244