1 #pragma once
2 
3 #ifndef TNZ_POPUPMENU_INCLUDED
4 #define TNZ_POPUPMENU_INCLUDED
5 
6 #include "tw/action.h"
7 #include "tw/popup.h"
8 #include "tw/button.h"
9 
10 #undef DVAPI
11 #undef DVVAR
12 #ifdef TWIN_EXPORTS
13 #define DVAPI DV_EXPORT_API
14 #define DVVAR DV_EXPORT_VAR
15 #else
16 #define DVAPI DV_IMPORT_API
17 #define DVVAR DV_IMPORT_VAR
18 #endif
19 
20 //-------------------------------------------------------------
21 
22 class TPopupMenu;
23 class TPopupMenuItem;
24 
25 //-------------------------------------------------------------
26 
27 class DVAPI TPopupMenuListener {
28 public:
TPopupMenuListener()29   TPopupMenuListener() {}
~TPopupMenuListener()30   virtual ~TPopupMenuListener() {}
31 
32   virtual void onMenuSelect(TPopupMenuItem *item) = 0;
33 };
34 
35 //-------------------------------------------------------------
36 
37 class DVAPI TPopupMenuItem : public TButton {
38   wstring m_title;
39   bool m_selected;
40 
41 public:
42   TPopupMenuItem(TPopupMenu *parent, string name);
43   void repaint();
44 
45   void enter(const TPoint &);
46   void leave(const TPoint &);
47 
48   void leftButtonDown(const TMouseEvent &e);
49   void leftButtonUp(const TMouseEvent &e);
50 
51   void setTitle(wstring title);
52 
53   TPopupMenu *getPopup();
54 
55   void select(bool on);
isSelected()56   bool isSelected() const { return m_selected; }
57 
58   virtual int getWidth();
59 };
60 
61 //-------------------------------------------------------------
62 
63 class DVAPI TPopupMenuSeparator : public TWidget {
64 public:
65   TPopupMenuSeparator(TPopupMenu *parent);
66   void repaint();
67 };
68 
69 //-------------------------------------------------------------
70 
71 //
72 // Note: to implement right-mouse-bottom menu use
73 // the class TContextMenu (see below)
74 //
75 
76 class DVAPI TPopupMenu : public TPopup {
77   TPopupMenuItem *m_currentItem;
78   TPopupMenuListener *m_listener;
79   int m_firstVisibleItem;
80   int m_visibleItemCount;
81   bool m_leftAlignment;
82 
83 public:
84   TPopupMenu(TWidget *parent, string name = "popupMenu");
85   void draw();
86   void configureNotify(const TDimension &);
87 
88   void leftButtonDrag(const TPoint &, UCHAR);
89   void leftButtonUp(const TPoint &);
90 
91   void popup(const TPoint &pos, int width = 120);
92   void close();
93 
getCurrentItem()94   TPopupMenuItem *getCurrentItem() { return m_currentItem; }
95   void setListener(TPopupMenuListener *);
96 
97   static TPopupMenu *getCurrentMenu();
98 
setLeftAlignment(bool a)99   void setLeftAlignment(bool a) { m_leftAlignment = a; }
100 
101 private:
102   void updateItemsVisibility();
103   void updateSize();
104   void computeSize(TPoint &pos, int maxY);
105 
106   friend class TPopupMenuArrow;
107 };
108 
109 //-------------------------------------------------------------
110 
111 //
112 // TContextMenu :
113 //  a class specifically dedicated to
114 //  right-mouse-button popup menu (aka Context Menu)
115 //
116 // Note: DON'T use the method popup() (inherited from TPopupMenu)
117 //
118 // Note: the context menu will be automatically destroyed
119 // DON'T keep a reference to the context menu
120 //
121 // see examples below
122 //
123 
124 /*---- Example 1 (position indipendent) ----
125 
126    void Pluto::rightButtonUp(const TMouseEvent &e) {
127      TContextMenu *menu = new TContextMenu(this);
128      menu->addCommand("MI_Cut");
129      menu->addCommand("MI_Copy");
130      menu->addCommand("MI_Paste");
131      menu->addCommand("MI_Clear");
132      TContextMenu::open(menu, e.m_pos);
133    }
134 
135 
136   ---- Example 2 (position dependent) ----
137 
138 
139    class MyContextMenu : public TContextMenu {
140      int m_myValue;
141    public:
142      MyContextMenu(TWidget*parent, int myValue)
143      : TContextMenu(parent), m_myValue(myValue), m_col(col) {
144         tconnect(this, "foo",  this, &CellContextMenu::onFoo);
145         tconnect(this, "bar",  this, &CellContextMenu::onBar);
146      }
147      void onFoo() { ... }
148      void onBar() { ... }
149    };
150 
151    void Pluto::rightButtonUp(const TMouseEvent &e) {
152      int row = ....
153      int col = ....
154      TContextMenu::open(new CellContextMenu(this, row, col), e.m_pos);
155    }
156 
157   -----------------------------------------*/
158 
159 class DVAPI TContextMenu : public TPopupMenu {
160 public:
161   class CommandFilter {
162   public:
163     virtual bool check(string cmdName) const = 0;
~CommandFilter()164     virtual ~CommandFilter() {}
165   };
166 
167   TContextMenu(TWidget *parent);
168 
169   void add(string name, TGenericCommandAction *action);
170   void addCommand(string cmdName);
171   void addCommand(string cmdName, TGenericCommandAction *action);
172 
addSeparator()173   void addSeparator() { new TPopupMenuSeparator(this); }
174 
175   /*
176 template <class T>
177 inline void addCommand(string cmdName, T*target, void (T::*method)()) {
178 //addCommand(cmdName, new TCommandAction<T>(target, method));
179 }
180 */
181   static void open(TContextMenu *menu, const TPoint &pos);
182 
183   static void setCommandFilter(CommandFilter *filter);
184 
185   void onTimer(int);
186 };
187 
188 template <class T>
tconnect(TContextMenu * menu,string cmdName,T * target,void (T::* method)())189 inline void tconnect(TContextMenu *menu, string cmdName, T *target,
190                      void (T::*method)()) {
191   menu->addCommand(cmdName, new TCommandAction<T>(target, method));
192 }
193 
194 template <class T, class Arg>
tconnect(TContextMenu * menu,string cmdName,T * target,void (T::* method)(Arg),Arg arg)195 inline void tconnect(TContextMenu *menu, string cmdName, T *target,
196                      void (T::*method)(Arg), Arg arg) {
197   menu->addCommand(cmdName, new TCommandAction1<T, Arg>(target, method, arg));
198 }
199 
200 #endif
201