1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // Menu.hh for Blackbox - an X11 Window manager
3 // Copyright (c) 2001 - 2005 Sean 'Shaleh' Perry <shaleh@debian.org>
4 // Copyright (c) 1997 - 2000, 2002 - 2005
5 //         Bradley T Hughes <bhughes at trolltech.com>
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 #ifndef __Menu_hh
26 #define __Menu_hh
27 
28 #include "Color.hh"
29 #include "EventHandler.hh"
30 #include "Font.hh"
31 #include "Rect.hh"
32 #include "Texture.hh"
33 #include "Timer.hh"
34 #include "Util.hh"
35 
36 #include <list>
37 #include <vector>
38 
39 namespace bt {
40 
41   class Application;
42   class Menu;
43 
44   class MenuItem
45   {
46   public:
47     enum Type { Normal, Separator };
MenuItem(Type t,const ustring & l=ustring ())48     inline MenuItem(Type t, const ustring &l = ustring())
49       : sub(0), lbl(l), ident(~0u), indx(~0u), height(0),
50         separator(t == Separator),
51         active(0), title(0), enabled(1), checked(0)
52     { }
MenuItem(Menu * s,const ustring & l)53     inline MenuItem(Menu *s, const ustring &l)
54       : sub(s), lbl(l), ident(~0u), indx(~0u), height(0), separator(0),
55         active(0), title(0), enabled(1), checked(0)
56     { }
57 
isSeparator(void) const58     inline bool isSeparator(void) const
59     { return bool(separator); }
isActive(void) const60     inline bool isActive(void) const
61     { return bool(active); }
isTitle(void) const62     inline bool isTitle(void) const
63     { return bool(title); }
isEnabled(void) const64     inline bool isEnabled(void) const
65     { return bool(enabled); }
isChecked(void) const66     inline bool isChecked(void) const
67     { return bool(checked); }
68 
id(void) const69     inline unsigned int id(void) const
70     { return ident; }
index(void) const71     inline unsigned int index(void) const
72     { return indx; }
73 
submenu(void) const74     inline Menu *submenu(void) const
75     { return sub; }
76 
label(void) const77     inline const ustring &label(void) const
78     { return lbl; }
79 
80   private:
81     Menu *sub;
82     ustring lbl;
83     unsigned int ident;
84     unsigned int indx;
85     unsigned int height;
86     unsigned int separator : 1;
87     unsigned int active    : 1;
88     unsigned int title     : 1;
89     unsigned int enabled   : 1;
90     unsigned int checked   : 1;
91 
92     friend class Menu;
93   };
94 
95 
96   class Resource;
97 
98   class MenuStyle : public NoCopy
99   {
100   public:
101     static MenuStyle *get(Application &app, unsigned int screen);
102 
103     void load(const Resource &resource);
104 
105     // fixed metrics
106     unsigned int separatorHeight(void) const;
107     unsigned int titleMargin(void) const;
108     unsigned int frameMargin(void) const;
109     unsigned int itemMargin(void) const;
110 
111     // textures
titleTexture(void) const112     inline const Texture &titleTexture(void) const
113     { return title.texture; }
frameTexture(void) const114     inline const Texture &frameTexture(void) const
115     { return frame.texture; }
activeTexture(void) const116     inline const Texture &activeTexture(void) const
117     { return active.texture; }
118 
119     // colors
titleForegroundColor(void) const120     inline const bt::Color &titleForegroundColor(void) const
121     { return title.foreground; }
titleTextColor(void) const122     inline const bt::Color &titleTextColor(void) const
123     { return title.text; }
frameForegroundColor(void) const124     inline const bt::Color &frameForegroundColor(void) const
125     { return frame.foreground; }
frameTextColor(void) const126     inline const bt::Color &frameTextColor(void) const
127     { return frame.text; }
128 
129     // fonts
titleFont(void) const130     inline const Font &titleFont(void) const
131     { return title.font; }
frameFont(void) const132     inline const Font &frameFont(void) const
133     { return frame.font; }
134 
135     // size calculations
136     Rect titleRect(const ustring &text) const;
137     Rect itemRect(const MenuItem &item) const;
138 
139     // drawing
140     void drawTitle(Window window, const Rect &rect,
141                    const ustring &text) const;
142     void drawItem(Window window, const Rect &rect,
143                   const MenuItem &item, Pixmap activePixmap) const;
144 
145   private:
146     MenuStyle(Application &app, unsigned int screen);
147 
148     Application &_app;
149     unsigned int _screen;
150     struct _title {
151       Texture texture;
152       Color foreground;
153       Color text;
154       Font font;
155       Alignment alignment;
156     } title;
157     struct _frame {
158       Texture texture;
159       Color foreground;
160       Color text;
161       Color disabled;
162       Font font;
163       Alignment alignment;
164     } frame;
165     struct _active {
166       Texture texture;
167       Color foreground;
168       Color text;
169       // font and alignment used from frame above
170     } active;
171     unsigned int title_margin, frame_margin, item_indent;
172 
173     static MenuStyle **styles;
174   };
175 
176 
177   class Menu : public EventHandler, public NoCopy
178   {
179   public:
180     Menu(Application &app, unsigned int screen);
181     virtual ~Menu(void);
182 
windowID(void) const183     inline Window windowID(void) const
184     { return _window; }
185 
186     unsigned int insertItem(const MenuItem &item,
187                             unsigned int id = ~0u,
188                             unsigned int index = ~0u);
189 
insertItem(const ustring & label,unsigned int id=~0u,unsigned int index=~0u)190     inline unsigned int insertItem(const ustring &label,
191                                    unsigned int id = ~0u,
192                                    unsigned int index = ~0u)
193     { return insertItem(MenuItem(MenuItem::Normal, label), id, index); }
194 
insertItem(const ustring & label,Menu * submenu,unsigned int id=~0u,unsigned int index=~0u)195     inline unsigned int insertItem(const ustring &label,
196                                    Menu *submenu,
197                                    unsigned int id = ~0u,
198                                    unsigned int index = ~0u)
199     { return insertItem(MenuItem(submenu, label), id, index); }
200 
insertSeparator(unsigned int index=~0u)201     inline void insertSeparator(unsigned int index = ~0u)
202     { (void) insertItem(MenuItem(MenuItem::Separator), ~0u, index); }
203 
204 
205     void changeItem(unsigned int id,
206                     const ustring &newlabel,
207                     unsigned int newid = ~0u);
208 
209     void setItemEnabled(unsigned int id, bool enabled);
210     bool isItemEnabled(unsigned int id) const;
211 
212     void setItemChecked(unsigned int id, bool checked);
213     bool isItemChecked(unsigned int id) const;
214 
215     void removeItem(unsigned int id);
216     void removeIndex(unsigned int index);
217     void clear(void);
218 
count(void) const219     inline unsigned int count(void) const
220     { return _items.size(); }
221 
title(void) const222     inline const ustring &title(void) const
223     { return _title; }
setTitle(const ustring & newtitle)224     inline void setTitle(const ustring &newtitle)
225     { _title = newtitle; }
226     void showTitle(void);
227     void hideTitle(void);
228 
isVisible(void) const229     inline bool isVisible(void) const
230     { return _visible; }
231 
232     void popup(int x, int y,
233                bool centered = true);
234     virtual void popup(int x, int y,
235                        const Rect &constraint,
236                        bool centered = true);
237     void move(int x, int y);
238     virtual void show(void);
239     virtual void hide(void);
240 
241     virtual void refresh(void);
242     virtual void reconfigure(void);
243 
autoDelete(void) const244     inline bool autoDelete(void) const
245     { return _auto_delete; }
setAutoDelete(bool ad)246     inline void setAutoDelete(bool ad)
247     { _auto_delete = ad; }
248 
249   protected:
250     virtual void buttonPressEvent(const XButtonEvent * const event);
251     virtual void buttonReleaseEvent(const XButtonEvent * const event);
252     virtual void motionNotifyEvent(const XMotionEvent * const event);
253     virtual void leaveNotifyEvent(const XCrossingEvent * const /*unused*/);
254     virtual void exposeEvent(const XExposeEvent * const event);
255     virtual void keyPressEvent(const XKeyEvent * const event);
256 
257     virtual void titleClicked(unsigned int button);
258     virtual void itemClicked(unsigned int id, unsigned int button);
259 
260     virtual void hideAll(void);
261 
262     virtual void tearOff(void);
263 
264     Rect geometry(void) const;
265 
266   private:
267     void updateSize(void);
268     void updatePixmaps(void);
269 
270     typedef std::list<MenuItem> ItemList;
271 
272     unsigned int verifyId(unsigned int id = ~0u);
273     void activateItem(const Rect &rect, MenuItem &item);
274     void deactivateItem(const Rect &rect, MenuItem &item,
275                         bool hide_submenu = true);
276     void activateIndex(unsigned int index);
277     void showActiveSubmenu(void);
278 
279     ItemList::iterator findItem(unsigned int id, Rect& r);
280 
281     void activateSubmenu(void);
282     void positionRect(Rect& r, int &row, int &col);
283     void invalidateSize(void);
284 
285     void removeItemByIterator(ItemList::iterator& it);
286 
287     Application &_app;
288     unsigned int _screen;
289 
290     Window _window;
291     Pixmap _tpixmap, _fpixmap, _apixmap;
292 
293     Rect _rect;  // entire menu
294     Rect _trect; // title
295     Rect _frect; // frame
296     Rect _irect; // items inside the frame
297 
298     Timer _timer;
299     ustring _title;
300 
301     ItemList _items;
302     std::vector<bool> _id_bits;
303 
304     Menu *_parent_menu;
305     Menu *_current_submenu;
306     Menu *_active_submenu;
307     unsigned int _motion;
308     unsigned int _itemw;
309     unsigned int _active_index;
310     bool _auto_delete;
311     bool _pressed;
312     bool _title_pressed;
313     bool _size_dirty;
314     bool _show_title;
315     bool _visible;
316     bool _tornoff;
317   };
318 
319 } // namespace bt
320 
321 #endif // __Menu_hh
322