00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00033 #ifndef PG_POPUPMENU_H
00034 #define PG_POPUPMENU_H
00035
00036 #include "pgthemewidget.h"
00037 #include "pgsignals.h"
00038 #include "pgstring.h"
00039
00040 #include <string>
00041 #include <list>
00042 #ifdef HASH_MAP_INC
00043 # include HASH_MAP_INC
00044 #else
00045 # include <map>
00046 #endif
00047
00068 class DECLSPEC PG_PopupMenu : public PG_ThemeWidget {
00069 public:
00070
00087 class DECLSPEC MenuItem : public PG_Rect, public PG_MessageObject {
00088 public:
00089 enum MI_FLAGS {
00090 MIF_NONE = 0,
00091 MIF_DISABLED = 0x01,
00092 MIF_SEPARATOR = 0x02,
00093 MIF_SUBMENU = 0x04
00094 };
00095
00099 template<class datatype = PG_Pointer>
00100 class SignalSelectMenuItem : public PG_Signal1<MenuItem*, datatype> {}
00101 ;
00102
00103 SignalSelectMenuItem<> sigSelectMenuItem;
00104
00105 typedef SigC::Slot2<bool, MenuItem*, PG_Pointer> MenuItemSlot;
00106
00107 public:
00108 MenuItem(PG_PopupMenu *parent,
00109 const std::string& caption,
00110 int id,
00111 MI_FLAGS flags);
00112 MenuItem(PG_PopupMenu *parent,
00113 const std::string& caption,
00114 PG_PopupMenu *submenu);
00115 ~MenuItem();
00116
00117 bool measureItem(PG_Rect* rect, bool full = false);
00118 bool isPointInside(int x, int y);
00119 inline void moveTo(int x, int y);
00120
00121 inline SDL_Surface* getNormal() const;
00122 inline SDL_Surface* getDisabled() const;
00123 inline SDL_Surface* getSelected() const;
00124
00125 bool paintNormal(SDL_Surface *canvas, PG_Color* tcol, PG_Color* scol = NULL);
00126 bool paintDisabled(SDL_Surface *canvas, PG_Color* tcol, PG_Color* scol = NULL);
00127 bool paintSelected(SDL_Surface *canvas, PG_Color* tcol, PG_Color* scol = NULL);
00128
00129 inline void disable();
00130 inline void enable();
00131 inline bool isDisabled() const;
00132 inline bool isEnabled() const;
00133 inline void select();
00134 inline void unselect();
00135 inline bool isSelected() const;
00136 inline bool isSeparator() const;
00137 inline bool isSubMenu() const;
00138 inline bool isMute() const;
00139
00140 inline int Width() const;
00141 inline int Height() const;
00142
00143 inline int getId() const;
00144 inline PG_PopupMenu *getSubMenu() const;
00145
00146 inline const PG_String& getCaption() const;
00147
00148 inline operator PG_Point const&() const;
00149
00150 private:
00151 DLLLOCAL void initItem( const std::string& caption );
00152 DLLLOCAL bool renderSurface(SDL_Surface *canvas, SDL_Surface **text, PG_Color* tcol, PG_Color* scol = 0);
00153 DLLLOCAL bool isValidRect();
00154
00155 protected:
00156 unsigned myFlags;
00157 PG_String myCaption;
00158 PG_String myRightCaption;
00159 PG_PopupMenu *myParent;
00160
00161 PG_PopupMenu *mySubMenu;
00162 int myId;
00163
00164 SDL_Surface *sNormal;
00165 SDL_Surface *sSelected;
00166 SDL_Surface *sDisabled;
00167
00168 bool selected;
00169
00170 private:
00171 bool needRecalc;
00172 PG_Point myPoint;
00173 };
00174
00175 #ifndef DOXYGEN_SKIP
00176 class item_with_id : public std::unary_function<MenuItem*, bool> {
00177 int id;
00178
00179 public:
00180 explicit item_with_id(int i)
00181 : id(i) {}
00182
00183 bool operator() (const MenuItem* const mi) const {
00184 return mi->getId() == id;
00185 }
00186 };
00187 #endif // DOXYGEN_SKIP
00188
00189 public:
00190
00194 template<class datatype = PG_Pointer>
00195 class SignalSelectMenuItem : public PG_Signal1<MenuItem*, datatype> {}
00196 ;
00197
00198 PG_PopupMenu(PG_Widget *parent,
00199 int x, int y,
00200 const std::string& caption = PG_NULLSTR,
00201 const std::string& style = "PopupMenu");
00202
00203 ~PG_PopupMenu();
00204
00223 PG_PopupMenu& addMenuItem(const std::string& caption,
00224 int ID,
00225 MenuItem::MenuItemSlot,
00226 PG_Pointer data = NULL,
00227 MenuItem::MI_FLAGS flags = MenuItem::MIF_NONE);
00228
00229 PG_PopupMenu& addMenuItem(const std::string& caption,
00230 int ID,
00231 MenuItem::MI_FLAGS flags = MenuItem::MIF_NONE);
00232
00233 PG_PopupMenu& addMenuItem(const std::string& caption,
00234 PG_PopupMenu *sub,
00235 MenuItem::MI_FLAGS flags = MenuItem::MIF_SUBMENU);
00236
00242 PG_PopupMenu& addSeparator();
00243
00244 bool SetMenuItemSlot(int id, MenuItem::MenuItemSlot slot, PG_Pointer clientdata = NULL);
00245
00246 inline int maxItemWidth() const;
00247
00248 void disableItem(int dd);
00249 void enableItem(int id);
00250
00262 void trackMenu(int x = -1, int y = -1);
00263 void openMenu(int x = -1, int y = -1);
00264
00265
00266 SignalSelectMenuItem<> sigSelectMenuItem;
00267
00268 protected:
00269
00270 typedef std::list<MenuItem*>::iterator MII;
00271
00272
00273 void eventBlit(SDL_Surface* surface, const PG_Rect& src, const PG_Rect& dst);
00274
00275 void eventMouseEnter();
00276 void eventMouseLeave();
00277
00278 bool eventMouseMotion(const SDL_MouseMotionEvent *motion);
00279 bool eventMouseButtonDown(const SDL_MouseButtonEvent *button);
00280 bool eventMouseButtonUp(const SDL_MouseButtonEvent *button);
00281 bool eventKeyDown(const SDL_KeyboardEvent *key);
00282
00283 void eventMoveWidget(int x, int y);
00284 void eventShow();
00285 void eventHide();
00286
00287 void LoadThemeStyle(const std::string& widgettype);
00288 void LoadThemeStyle(const std::string& widgettype, const std::string& objectname);
00289
00290
00291 virtual bool getCaptionHeight(PG_Rect &rect, bool constructing = false);
00292 virtual void recalcRect();
00293 virtual void handleClick(int x, int y);
00294 virtual void enslave(PG_PopupMenu *master);
00295 virtual void liberate();
00296
00297 private:
00298
00299 DLLLOCAL bool selectItem(MenuItem *item, MII iter);
00300 DLLLOCAL bool handleMotion(PG_Point const&);
00301 DLLLOCAL void appendItem(MenuItem *item);
00302
00303 protected:
00304
00305 std::list<MenuItem*> items;
00306 std::string myCaption;
00308 PG_Color captionActiveColor;
00309 PG_Color captionInactiveColor;
00310
00311 PG_Color miNormalColor;
00312 PG_Color miSelectedColor;
00313 PG_Color miDisabledColor;
00314
00315 PG_Color sepNormalColor;
00316 PG_Color sepShadowColor;
00317
00318 int xPadding;
00319 int yPadding;
00320
00323 int minTabWidth;
00324
00325 int separatorLineWidth;
00326
00327 private:
00328 PG_Rect captionRect;
00329 PG_Rect actionRect;
00330
00331 PG_Gradient *miGradients[3];
00332 SDL_Surface *miBackgrounds[3];
00333 PG_Draw::BkMode miBkModes[3];
00334 Uint8 miBlends[3];
00335 int itemHeight;
00336 int lastH;
00337 MenuItem *selected;
00338
00339 bool tracking;
00340 bool wasTracking;
00341 bool buttonDown;
00342
00343 MII stop;
00344 MII start;
00345 MII current;
00346
00347 PG_PopupMenu *activeSub;
00348 PG_PopupMenu *myMaster;
00349 MenuItem *subParent;
00350 };
00351
00352 inline int PG_PopupMenu::maxItemWidth() const {
00353 return w - xPadding;
00354 }
00355
00356 inline void PG_PopupMenu::MenuItem::moveTo(int _x, int _y) {
00357 myPoint.x = x = _x;
00358 myPoint.y = y = _y;
00359 };
00360
00361 inline SDL_Surface* PG_PopupMenu::MenuItem::getNormal() const {
00362 return sNormal;
00363 }
00364
00365 inline SDL_Surface* PG_PopupMenu::MenuItem::getDisabled() const {
00366 return sDisabled;
00367 }
00368
00369 inline SDL_Surface* PG_PopupMenu::MenuItem::getSelected() const {
00370 return sSelected;
00371 }
00372
00373 inline void PG_PopupMenu::MenuItem::disable() {
00374 myFlags |= MIF_DISABLED;
00375 }
00376
00377 inline void PG_PopupMenu::MenuItem::enable() {
00378 myFlags &= ~MIF_DISABLED;
00379 }
00380
00381 inline bool PG_PopupMenu::MenuItem::isDisabled() const {
00382 return (myFlags & MIF_DISABLED);
00383 }
00384
00385 inline bool PG_PopupMenu::MenuItem::isEnabled() const {
00386 return !(myFlags & MIF_DISABLED);
00387 }
00388
00389 inline void PG_PopupMenu::MenuItem::select() {
00390 selected = true;
00391 }
00392
00393 inline void PG_PopupMenu::MenuItem::unselect() {
00394 selected = false;
00395 }
00396
00397 inline bool PG_PopupMenu::MenuItem::isSelected() const {
00398 return selected;
00399 }
00400
00401 inline bool PG_PopupMenu::MenuItem::isSeparator() const {
00402 return ((myFlags & MIF_SEPARATOR) != 0);
00403 }
00404
00405 inline bool PG_PopupMenu::MenuItem::isSubMenu() const {
00406 return ((myFlags & MIF_SUBMENU) != 0);
00407 }
00408
00409 inline bool PG_PopupMenu::MenuItem::isMute() const {
00410 return ((myFlags & MIF_DISABLED) ||
00411 (myFlags & MIF_SEPARATOR));
00412 }
00413
00414 inline int PG_PopupMenu::MenuItem::Width() const {
00415 return w;
00416 }
00417
00418 inline int PG_PopupMenu::MenuItem::Height() const {
00419 return h;
00420 }
00421
00422 inline int PG_PopupMenu::MenuItem::getId() const {
00423 return myId;
00424 }
00425
00426 inline PG_PopupMenu *PG_PopupMenu::MenuItem::getSubMenu() const {
00427 return mySubMenu;
00428 }
00429
00430 inline const PG_String& PG_PopupMenu::MenuItem::getCaption() const {
00431 return myCaption;
00432 }
00433
00434 inline PG_PopupMenu::MenuItem::operator PG_Point const&() const {
00435 return myPoint;
00436 }
00437
00438 #endif // PG_POPUPMENU_H