Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

pgpopupmenu.cpp

Go to the documentation of this file.
00001 /*
00002    ParaGUI - crossplatform widgetset
00003    Copyright (C) 2000,2001,2002  Alexander Pipelka
00004  
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009  
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014  
00015    You should have received a copy of the GNU Library General Public
00016    License along with this library; if not, write to the Free
00017    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018  
00019    Alexander Pipelka
00020    pipelka@teleweb.at
00021  
00022    Last Update:      $Author: mbickel $
00023    Update Date:      $Date: 2008-05-01 16:18:12 $
00024    Source File:      $Source: /home/cvspsrv/cvsroot/games/asc/source/libs/paragui/src/widgets/pgpopupmenu.cpp,v $
00025    CVS/RCS Revision: $Revision: 1.3 $
00026    Status:           $State: Exp $
00027  */
00028 
00029 #include "pgdraw.h"
00030 #include "pgapplication.h"
00031 #include "pgpopupmenu.h"
00032 #include "pgtheme.h"
00033 #include "pgeventsupplier.h"
00034 
00035 #include <functional>
00036 #include <algorithm>
00037 #include <iostream>
00038 
00039 /***********************************
00040  * MenuItem
00041  */
00042 PG_PopupMenu::MenuItem::MenuItem(PG_PopupMenu *parent, const std::string& caption, int id, MI_FLAGS flags)
00043                 : myFlags(flags),
00044                 myParent(parent),
00045                 mySubMenu(0),
00046                 myId(id),
00047                 sNormal(0),
00048                 sSelected(0),
00049                 sDisabled(0),
00050                 selected(false),
00051       needRecalc(true) {
00052         initItem( caption );
00053         myFlags &= ~MIF_SUBMENU;
00054 }
00055 
00056 PG_PopupMenu::MenuItem::MenuItem(PG_PopupMenu *parent, const std::string& caption, PG_PopupMenu *submenu)
00057                 : myFlags(MIF_SUBMENU),
00058                 myParent(parent),
00059                 mySubMenu(submenu),
00060                 myId(-1),
00061                 sNormal(0),
00062                 sSelected(0),
00063                 sDisabled(0),
00064                 selected(false),
00065 needRecalc(true) {
00066         initItem( caption );
00067 }
00068 
00069 PG_PopupMenu::MenuItem::~MenuItem() {}
00070 
00071 void PG_PopupMenu::MenuItem::initItem( const std::string& caption ) {
00072         my_xpos = my_ypos = my_height = my_width = 0;
00073         myPoint.x = myPoint.y = 0;
00074 
00075 
00076         std::string::size_type tabPos = caption.find('\t');
00077         if ( tabPos != std::string::npos && tabPos < caption.length()-1 ) {
00078                 myCaption  = caption.substr(0,tabPos);
00079                 myRightCaption = caption.substr(tabPos+1 );
00080         } else {
00081                 myCaption = caption;
00082         }
00083 
00084         measureItem(this);
00085         needRecalc = false;
00086 
00087         if (myCaption.empty())
00088                 myFlags |= MIF_SEPARATOR;
00089 }
00090 
00091 bool PG_PopupMenu::MenuItem::measureItem(PG_Rect* rect, bool full) {
00092 
00093         rect->x = x;
00094         rect->y = y;
00095 
00096         if (isSeparator()) {
00097                 rect->w = myParent->maxItemWidth();
00098                 rect->h = 3;
00099 
00100                 return true;
00101         } else if (myCaption.empty())
00102                 return false;
00103 
00104         if (!needRecalc) {
00105                 if (!full)
00106                         rect->w = my_width;
00107                 else
00108                         rect->w = myParent->maxItemWidth();
00109 
00110                 rect->h = my_height;
00111 
00112                 return true;
00113         }
00114 
00115         Uint16 w,h;
00116 
00117         if ( myRightCaption.length()  ) {
00118                 PG_Widget::GetTextSize(
00119                     w, h,
00120                     myCaption,
00121                     myParent->GetFont());
00122 
00123                 rect->w = w;
00124                 rect->h = h;
00125 
00126                 PG_Widget::GetTextSize(
00127                     w, h,
00128                     myRightCaption,
00129                     myParent->GetFont());
00130 
00131                 rect->w = rect->w + w + myParent->minTabWidth;
00132                 if ( h > rect->h )
00133                         rect->h = h;
00134         } else {
00135                 PG_Widget::GetTextSize(
00136                     w, h,
00137                     myCaption,
00138                     myParent->GetFont());
00139 
00140                 rect->w = w;
00141                 rect->h = h;
00142         }
00143 
00144         //+++
00145         //    TTF_SizeText(myFont, myCaption.c_str(),
00146         //                 reinterpret_cast<int*>(&(rect->w)),
00147         //                 reinterpret_cast<int*>(&(rect->h)));
00148 
00149         //    rect->h += abs(TTF_FontDescent(myFont)) + (TTF_FontAscent(myFont) - rect->h);
00150         if (full)
00151                 rect->w = myParent->maxItemWidth();
00152 
00153         return true;
00154 }
00155 
00156 bool PG_PopupMenu::MenuItem::isPointInside(int x, int y) {
00157         int posx = x - my_xpos;
00158         int posy = y - my_ypos;
00159 
00160         if ((posx >= 0) && (posx <= my_width) &&
00161                 (posy >= 0) && (posy <= my_height))
00162                 return true;
00163 
00164         return false;
00165 }
00166 
00167 bool PG_PopupMenu::MenuItem::renderSurface(SDL_Surface *canvas, SDL_Surface **text, PG_Color* tcol, PG_Color* scol) {
00168         if (/*!*text ||*/ !canvas)
00169                 return false;
00170 
00171         SDL_Rect      blitRect;
00172         blitRect.x = x + myParent->x;
00173         blitRect.y = y  + myParent->y;
00174         blitRect.w = myParent->maxItemWidth();
00175         blitRect.h = h;
00176 
00177         if ( myFlags & MIF_SEPARATOR ) {
00178                 PG_Draw::DrawLine(canvas, blitRect.x, blitRect.y + 1, blitRect.x + myParent->maxItemWidth(), blitRect.y + 1, myParent->GetFont()->GetColor(), myParent->separatorLineWidth );
00179         } else {
00180                 myParent->SetFontColor(*tcol);
00181                 if ( myRightCaption.length()  ) {
00182                         Uint16 tw,th;
00183 
00184                         PG_Widget::GetTextSize( tw, th, myRightCaption, myParent->GetFont());
00185 
00186                         RenderText(canvas, blitRect, blitRect.x + myParent->maxItemWidth() - tw, blitRect.y+myParent->GetFontAscender(), myRightCaption, myParent->GetFont());
00187                 }
00188                 RenderText(canvas, blitRect, blitRect.x, blitRect.y+myParent->GetFontAscender(), myCaption, myParent->GetFont());
00189 
00190         }
00191         //SDL_BlitSurface(*text, NULL, canvas, &blitRect);
00192 
00193         return true;
00194 }
00195 
00196 inline bool PG_PopupMenu::MenuItem::isValidRect() {
00197         if ((my_width > 0) && (my_height > 0))
00198                 return true;
00199 
00200         return false;
00201 }
00202 
00203 inline bool PG_PopupMenu::MenuItem::paintNormal(SDL_Surface *canvas, PG_Color* tcol, PG_Color* scol) {
00204         if (!isValidRect())
00205                 return false;
00206 
00207         return renderSurface(canvas, &sNormal, tcol, scol);
00208 }
00209 
00210 inline bool PG_PopupMenu::MenuItem::paintSelected(SDL_Surface *canvas, PG_Color* tcol, PG_Color* scol) {
00211         if (!isValidRect())
00212                 return false;
00213 
00214         return renderSurface(canvas, &sSelected, tcol, scol);
00215 }
00216 
00217 inline bool PG_PopupMenu::MenuItem::paintDisabled(SDL_Surface *canvas, PG_Color* tcol, PG_Color* scol) {
00218         if (!isValidRect())
00219                 return false;
00220 
00221         return renderSurface(canvas, &sDisabled, tcol, scol);
00222 }
00223 
00224 /***********************************
00225  * PG_PopupMenu
00226  */
00227 PG_PopupMenu::PG_PopupMenu(PG_Widget *parent,
00228                            int x, int y,
00229                            const std::string& caption,
00230                            const std::string& style)
00231                 : PG_ThemeWidget(parent, PG_Rect(0, 0, 1, 1)),
00232                 xPadding(0),
00233                 yPadding(0),
00234                 minTabWidth(5),
00235                 separatorLineWidth(1),
00236                 itemHeight(0),
00237                 selected(0),
00238                 tracking(false),
00239       wasTracking(false),
00240                 buttonDown(false),
00241                 activeSub(0),
00242 myMaster(0) {
00243         for (int i = 0; i < 3; i++) {
00244                 miBackgrounds[i] = NULL;
00245         }
00246         LoadThemeStyle(style);
00247 
00248         myCaption = caption;
00249 
00250         getCaptionHeight(captionRect, true);
00251 
00252         MoveWidget(PG_Rect(x, y, captionRect.my_width + xPadding, captionRect.my_height + yPadding));
00253 
00254         captionRect.my_xpos = (my_width - captionRect.my_width) >> 1;
00255 
00256         lastH = my_height - (yPadding >> 1) + 1;
00257 
00258         current  = start = items.begin();
00259         stop = items.end();
00260 }
00261 
00262 PG_PopupMenu::~PG_PopupMenu() {
00263         for (int i = 0; i < 3; i++) {
00264                 if (miBackgrounds[i]) {
00265                         PG_Application::UnloadSurface(miBackgrounds[i]);
00266                 }
00267         }
00268 
00269         for (MII j = start; j != stop; j++)
00270                 delete (*j);
00271 }
00272 
00273 void PG_PopupMenu::appendItem(MenuItem *item) {
00274         PG_Rect     rect;
00275 
00276         items.push_back(item);
00277         item->measureItem(&rect);
00278 
00279         item->moveTo(xPadding >> 1, lastH);
00280         lastH += rect.my_height;
00281 
00282         if (!itemHeight)
00283                 itemHeight = rect.my_height;
00284 
00285         stop = items.end();
00286         current = start = items.begin();
00287 
00288         recalcRect();
00289 
00290         selected = *start;
00291         current = start;
00292         selected->select();
00293 }
00294 
00295 PG_PopupMenu& PG_PopupMenu::addMenuItem(const std::string& caption,
00296                                         int ID,
00297                                         MenuItem::MenuItemSlot handler,
00298                                         PG_Pointer data,
00299                                         MenuItem::MI_FLAGS flags) {
00300 
00301         MenuItem* item = new MenuItem(this, caption, ID, flags);
00302         appendItem(item);
00303         item->sigSelectMenuItem.connect(handler, data);
00304 
00305         return *this;
00306 }
00307 
00308 PG_PopupMenu& PG_PopupMenu::addMenuItem(const std::string& caption,
00309                                         int ID,
00310                                         MenuItem::MI_FLAGS flags) {
00311 
00312         MenuItem* item = new MenuItem(this, caption, ID, flags);
00313         appendItem(item);
00314 
00315         return *this;
00316 }
00317 
00318 PG_PopupMenu& PG_PopupMenu::addMenuItem(const std::string& caption,
00319                                         PG_PopupMenu *sub,
00320                                         MenuItem::MI_FLAGS flags) {
00321         MenuItem    *item = new MenuItem(this, caption, sub);
00322 
00323         appendItem(item);
00324 
00325         return *this;
00326 }
00327 
00328 /*PG_PopupMenu& PG_PopupMenu::addMenuItem(char *caption,
00329                                         int ID,
00330                                         PG_Action *action,
00331                                         void *data,
00332                                         MenuItem::MI_FLAGS flags) {
00333         MenuItem    *item = new MenuItem(this, caption, ID, flags);
00334  
00335         appendItem(item);
00336  
00337         if (action) {
00338                 if (actions[ID])
00339                         //TODO: an exception here??
00340                         PG_LogWRN("Duplicate action ID %d - Replacing old value", ID);
00341                 actions[ID] = action;
00342         };
00343  
00344         return *this;
00345 }*/
00346 
00347 PG_PopupMenu& PG_PopupMenu::addSeparator() {
00348         // Ugly
00349         return addMenuItem(PG_NULLSTR, -1, MenuItem::MIF_SEPARATOR);
00350 }
00351 
00352 void PG_PopupMenu::disableItem(int id) {
00353         MII mi;
00354 
00355         mi = find_if(start, stop, item_with_id(id));
00356         if (*mi && mi != stop)
00357                 ((MenuItem*)*mi)->disable();
00358 }
00359 
00360 void PG_PopupMenu::enableItem(int id) {
00361         MII mi;
00362 
00363         mi = find_if(start, stop, item_with_id(id));
00364         if (*mi && mi != stop)
00365                 ((MenuItem*)*mi)->enable();
00366 }
00367 
00368 void PG_PopupMenu::trackMenu(int x, int y) {
00369         tracking = true;
00370         openMenu( x, y );
00371         buttonDown = PG_Application::GetEventSupplier()->GetMouseState( x,y ) & SDL_BUTTON_LEFT;
00372 }
00373 
00374 void PG_PopupMenu::openMenu(int x, int y) {
00375         if (x >= 0 && y >= 0) {
00376                 if (x != my_xpos && y != my_ypos)
00377                         MoveWidget(x, y);
00378         }
00379 
00380         x = my_xpos;
00381         y = my_ypos;
00382 
00383         if(x + my_width >= PG_Application::GetScreenWidth()) {
00384                 x = PG_Application::GetScreenWidth() - my_width;
00385         }
00386 
00387         if(y + my_height >= PG_Application::GetScreenHeight()) {
00388                 y = PG_Application::GetScreenHeight() - my_height;
00389         }
00390 
00391         if (x != my_xpos || y != my_ypos)
00392                 MoveWidget(x, y);
00393 
00394         Show();
00395 }
00396 
00397 bool PG_PopupMenu::getCaptionHeight(PG_Rect &rect, bool constructing) {
00398 
00399         if (myCaption.empty())
00400                 return false;
00401 
00402         Uint16 w = 0, h = 0;
00403 
00404         //+++
00405         GetTextSize(w, h, myCaption);
00406 
00407         // TODO: need to make sure caption isn't wider than screen
00408         if (!constructing)
00409                 rect.my_xpos = (my_width - w) / 2;
00410         else
00411                 rect.my_xpos = 0;
00412         rect.my_ypos = 0;
00413 
00414         rect.my_height = h;
00415         rect.my_width = w;
00416 
00417         return true;
00418 }
00419 
00420 void PG_PopupMenu::recalcRect() {
00421         PG_Rect newRect;
00422 
00423         getCaptionHeight(newRect);
00424         newRect.my_xpos = my_xpos;
00425         newRect.my_ypos = my_ypos;
00426         newRect.my_height += yPadding;
00427 
00428         if (!items.empty()) {
00429                 PG_Rect itemRect;
00430 
00431                 for (MII i = start; i != stop; i++) {
00432                         MenuItem* item = *i;
00433 
00434                         item->measureItem(&itemRect);
00435 
00436                         if (itemRect.my_width > newRect.my_width)
00437                                 newRect.my_width = itemRect.my_width;
00438                         newRect.my_height += itemRect.my_height;
00439                 }
00440         }
00441 
00442         if ((newRect.my_width != my_width) ||
00443                 (newRect.my_height != my_height)) {
00444                 int sh = PG_Application::GetScreenHeight();
00445                 int sw = PG_Application::GetScreenWidth();
00446 
00447                 if (newRect.my_height > sh)
00448                         newRect.my_height = sh;
00449 
00450                 if (newRect.my_width > sw)
00451                         newRect.my_width = sw;
00452 
00453                 SizeWidget(newRect.my_width + xPadding, newRect.my_height);
00454 
00455                 actionRect.my_xpos = my_xpos + (xPadding >> 1);
00456                 actionRect.my_ypos = my_ypos + captionRect.my_height + (yPadding >> 1);
00457                 actionRect.my_width = my_width - xPadding;
00458                 actionRect.my_height = my_height - xPadding - captionRect.my_height;
00459         }
00460 }
00461 
00462 void PG_PopupMenu::handleClick(int x, int y) {
00463         PG_Point  p;
00464 
00465         p.x = x;
00466         p.y = y;
00467 
00468         if (actionRect.IsInside(p)) {
00469                 if(!selected)
00470                         return;
00471 
00472                 if (!selected->isSubMenu()) {
00473                         if (!selected->isMute()) {
00474                                 // call item's callback
00475                                 selected->sigSelectMenuItem(selected);
00476                                 // call general callback (PG_PopupMenu)
00477                                 sigSelectMenuItem(selected);
00478                         }
00479                 }
00480 
00481                 selected->unselect();
00482                 selected = 0;
00483         }
00484 
00485         liberate();
00486 }
00487 
00488 void PG_PopupMenu::enslave(PG_PopupMenu *master) {
00489         myMaster = master;
00490 }
00491 
00492 void PG_PopupMenu::liberate() {
00493         Hide();
00494 
00495         // Pass it down
00496         if (activeSub) {
00497                 PG_PopupMenu *tmp = activeSub;
00498                 activeSub = 0;
00499                 tmp->liberate();
00500         }
00501 
00502         // Pass it up
00503         if (myMaster) {
00504                 myMaster->Hide();
00505                 myMaster->liberate();
00506                 myMaster = 0;
00507         }
00508 }
00509 
00510 void PG_PopupMenu::eventBlit(SDL_Surface* srf, const PG_Rect& src, const PG_Rect& dst) {
00511         SDL_Surface* surface = PG_Application::GetScreen();
00512         PG_ThemeWidget::eventBlit(srf, src, dst);
00513 
00514         if (!myCaption.empty()) {
00515                 SetFontColor(captionActiveColor);
00516                 DrawText(captionRect, myCaption);
00517         }
00518 
00519         if (!items.empty()) {
00520                 PG_Rect itemRect;
00521 
00522                 for (MII i = start; i != stop; i++) {
00523                         MenuItem* item = *i;
00524 
00525                         item->measureItem(&itemRect, true);
00526                         itemRect.x += my_xpos;
00527                         itemRect.y += my_ypos;
00528 
00529                         int statesel = 0;
00530                         if (item->isSelected())
00531                                 statesel = 1;
00532 
00533                         if (item->isDisabled())
00534                                 statesel = 2;
00535 
00536                         PG_Draw::DrawThemedSurface(surface, itemRect,
00537                                                    miGradients[statesel],
00538                                                    miBackgrounds[statesel],
00539                                                    miBkModes[statesel],
00540                                                    miBlends[statesel]);
00541 
00542                         switch(statesel) {
00543                                 case 0:
00544                                         if (item->isSeparator())
00545                                                 item->paintNormal(surface, &sepNormalColor, &sepShadowColor);
00546                                         else
00547                                                 item->paintNormal(surface, &miNormalColor);
00548                                         break;
00549 
00550                                 case 1:
00551                                         if (item->isSeparator())
00552                                                 item->paintSelected(surface, &sepNormalColor, &sepShadowColor);
00553                                         else
00554                                                 item->paintSelected(surface, &miSelectedColor);
00555                                         break;
00556 
00557                                 case 2:
00558                                         if (item->isSeparator())
00559                                                 item->paintDisabled(surface, &sepNormalColor, &sepShadowColor);
00560                                         else
00561                                                 item->paintDisabled(surface, &miDisabledColor);
00562                                         break;
00563                         }
00564                 }
00565         }
00566 }
00567 
00568 bool PG_PopupMenu::selectItem(MenuItem *item, MII iter) {
00569         if (selected)
00570                 selected->unselect();
00571         item->select();
00572         selected = item;
00573 
00574         if (current != iter)
00575                 current = iter;
00576 
00577         if (activeSub && subParent != selected) {
00578                 activeSub->Hide();
00579                 activeSub = 0;
00580         } else if (activeSub)
00581                 return false;
00582 
00583         if (!tracking && wasTracking) {
00584                 SetCapture();
00585                 tracking = true;
00586                 wasTracking = false;
00587         }
00588 
00589         if (selected->isSeparator())
00590                 return false;
00591 
00592         if (selected->isSubMenu()) {
00593                 if (tracking) {
00594                         ReleaseCapture();
00595                         tracking = false;
00596                         wasTracking = true;
00597                 }
00598 
00599                 PG_PopupMenu *sub = selected->getSubMenu();
00600                 activeSub = sub;
00601                 subParent = selected;
00602 
00603                 PG_Rect   rect;
00604 
00605                 sub->getCaptionHeight(rect);
00606                 sub->enslave(this);
00607                 sub->trackMenu(my_xpos + my_width - xPadding,
00608                                selected->my_ypos + my_ypos - rect.my_height);
00609 
00610                 return true;
00611         }
00612 
00613         return true;
00614 }
00615 
00616 bool PG_PopupMenu::handleMotion(PG_Point const &p) {
00617         MenuItem  *item = 0;
00618         PG_Rect    itemRect;
00619 
00620         if (current != stop) {
00621                 item = *current;
00622                 item->measureItem(&itemRect, true);
00623         } else
00624                 return false;
00625 
00626         if (item && itemRect.IsInside(p)) {
00627                 if (!selectItem(item, current))
00628                         return false;
00629         } else
00630                 for (MII i = start; i != stop; i++) {
00631                         item = *i;
00632                         item->measureItem(&itemRect, true);
00633                         itemRect.my_xpos += my_xpos;
00634                         itemRect.my_ypos += my_ypos;
00635 
00636                         if (itemRect.IsInside(p)) {
00637                                 if (!selectItem(item, i))
00638                                         return false;
00639                                 break;
00640                         }
00641                 }
00642 
00643         return true;
00644 }
00645 
00646 bool PG_PopupMenu::eventMouseMotion(const SDL_MouseMotionEvent *motion) {
00647         if (items.empty())
00648                 return false;
00649 
00650         PG_Point p;
00651 
00652         p.x = motion->x;
00653         p.y = motion->y;
00654 
00655         if (!actionRect.IsInside(p)) {
00656                 if (selected) {
00657                         selected->unselect();
00658                         selected = 0;
00659                         Redraw();
00660                 }
00661 
00662                 if (myMaster && tracking && myMaster->IsInside(p)) {
00663                         ReleaseCapture();
00664                         tracking = false;
00665                         wasTracking = true;
00666                         myMaster->ProcessEvent(reinterpret_cast<const SDL_Event*>(motion));
00667                 }
00668 
00669                 return false;
00670         }
00671 
00672         PG_Rect    itemRect;
00673         MenuItem  *oldSel = selected;
00674 
00675         if (selected) {
00676                 selected->measureItem(&itemRect, true);
00677                 itemRect.my_xpos += my_xpos;
00678                 itemRect.my_ypos += my_ypos;
00679                 if (itemRect.IsInside(p))
00680                         return false;
00681 
00682                 if (motion->yrel < 0  && current != start)
00683                         current--;
00684                 else if (motion->yrel > 0 && current != stop)
00685                         current++;
00686         } else {
00687                 current = start;
00688         }
00689 
00690         if (!handleMotion(p))
00691                 return false;
00692 
00693         if (oldSel != selected)
00694                 Redraw();
00695 
00696         return true;
00697 }
00698 
00699 bool PG_PopupMenu::eventMouseButtonDown(const SDL_MouseButtonEvent *button) {
00700         PG_ThemeWidget::eventMouseButtonDown(button);
00701 
00702         if (button->button == SDL_BUTTON_LEFT) {
00703                 buttonDown = true;
00704                 return true;
00705         }
00706 
00707         return false;
00708 }
00709 
00710 bool PG_PopupMenu::eventMouseButtonUp(const SDL_MouseButtonEvent *button) {
00711         PG_ThemeWidget::eventMouseButtonUp(button);
00712 
00713         if (button->button == SDL_BUTTON_LEFT && buttonDown) {
00714                 buttonDown = false;
00715 
00716                 if (activeSub) {
00717                         activeSub->liberate();
00718                         return true;
00719                 }
00720 
00721                 Hide();
00722 
00723                 if (selected && selected->isSeparator())
00724                         return true;
00725 
00726                 handleClick(button->x, button->y);
00727 
00728                 return false;
00729         }
00730 
00731         return false;
00732 }
00733 
00734 bool PG_PopupMenu::eventKeyDown(const SDL_KeyboardEvent *key) {
00735         SDL_KeyboardEvent key_copy = *key; // copy key structure
00736         PG_Application::TranslateNumpadKeys(&key_copy);
00737         // from now, we use key_copy which was copied or translated from key
00738    
00739 
00740    if ( key->keysym.unicode )
00741    for ( MII i = items.begin(); i != items.end(); ++i ) {
00742       if ( *i )
00743          if ( extractHotkey( (*i)->getCaption()) == key->keysym.unicode ) {
00744             Hide();
00745             if ( !(*i)->isDisabled()) {
00746                   // call item's callback
00747                (*i)->sigSelectMenuItem(selected);
00748                   // call general callback (PG_PopupMenu)
00749                sigSelectMenuItem((*i));
00750                return true;
00751             }
00752          }
00753    }
00754    
00755    
00756         switch (key_copy.keysym.sym) {
00757                 case SDLK_ESCAPE:
00758                         Hide();
00759                         break;
00760 
00761                 case SDLK_KP_ENTER:
00762                 case SDLK_RETURN:
00763                         if (selected) {
00764                                 Hide();
00765 
00766                                 if (/*actions[selected->getId()] &&*/ !selected->isDisabled()) {
00767                                         // call item's callback
00768                                         selected->sigSelectMenuItem(selected);
00769                                         // call general callback (PG_PopupMenu)
00770                                         sigSelectMenuItem(selected);
00771                                 }
00772 
00773                                 selected->unselect();
00774                                 selected = 0;
00775                         }
00776                         break;
00777 
00778                 case SDLK_UP:
00779                         if (items.empty())
00780                                 break;
00781 
00782                         if (current == start)
00783                                 current = stop;
00784 
00785                         do {
00786                                 current--;
00787                         } while ((current != start) && (*current)->isMute());
00788 
00789                         if (handleMotion(**current))
00790                                 Redraw();
00791                         break;
00792 
00793                 case SDLK_DOWN:
00794                         if (items.empty())
00795                                 break;
00796 
00797                         if (current == stop) {
00798                                 // special case
00799                                 current = start;
00800                                 while (current != stop && (*current)->isMute())
00801                                         current++;
00802                         } else
00803                                 do {
00804                                         current++;
00805                                 } while ((current != stop) && (*current)->isMute());
00806 
00807                         if (current == stop)
00808                                 return false;
00809 
00810                         if (handleMotion(**current))
00811                                 Redraw();
00812                         break;
00813 
00814                 default:
00815                         return false;
00816         }
00817 
00818         return true;
00819 }
00820 
00821 void PG_PopupMenu::eventMoveWidget(int x, int y) {
00822         PG_ThemeWidget::eventMoveWidget(x, y);
00823 
00824         actionRect.my_xpos = my_xpos + (xPadding >> 1);
00825         actionRect.my_ypos = my_ypos + captionRect.my_height + (yPadding >> 1);
00826 }
00827 
00828 void PG_PopupMenu::eventShow() {
00829         PG_ThemeWidget::eventShow();
00830 
00831         if (tracking) {
00832                 SetCapture();
00833         }
00834 
00835         current = start;
00836 }
00837 
00838 void PG_PopupMenu::eventHide() {
00839         PG_ThemeWidget::eventHide();
00840 
00841         if (tracking) {
00842                 ReleaseCapture();
00843                 tracking = false;
00844         }
00845 }
00846 
00847 void PG_PopupMenu::LoadThemeStyle(const std::string& widgettype) {
00848         PG_ThemeWidget::LoadThemeStyle(widgettype);
00849 
00850         PG_Theme *theme = PG_Application::GetTheme();
00851 
00852         // Global
00853         theme->GetProperty(widgettype, "PopupMenu", "xPadding", xPadding);
00854         theme->GetProperty(widgettype, "PopupMenu", "yPadding", yPadding);
00855         theme->GetProperty(widgettype, "PopupMenu", "minTabWidth", minTabWidth);
00856 
00857         // caption
00858         PG_ThemeWidget::LoadThemeStyle(widgettype, "Caption");
00859         theme->GetColor(widgettype, "Caption", "Active", captionActiveColor);
00860         theme->GetColor(widgettype, "Caption", "Inactive", captionInactiveColor);
00861         theme->GetColor(widgettype, "MenuItem", "Normal", miNormalColor);
00862         theme->GetColor(widgettype, "MenuItem", "Selected", miSelectedColor);
00863         theme->GetColor(widgettype, "MenuItem", "Disabled", miDisabledColor);
00864         theme->GetColor(widgettype, "MenuItem", "SepNormal", sepNormalColor);
00865         theme->GetColor(widgettype, "MenuItem", "SepShadow", sepShadowColor);
00866         theme->GetProperty(widgettype, "MenuItem", "separatorLineWidth", separatorLineWidth);
00867 
00868         miGradients[0] = theme->FindGradient(widgettype, "MenuItem", "gradientNormal");
00869         miGradients[1] = theme->FindGradient(widgettype, "MenuItem", "gradientSelected");
00870         miGradients[2] = theme->FindGradient(widgettype, "MenuItem", "gradientDisabled");
00871 
00872         miBackgrounds[0] = theme->FindSurface(widgettype, "MenuItem", "backNormal");
00873         miBackgrounds[1] = theme->FindSurface(widgettype, "MenuItem", "backSelected");
00874         miBackgrounds[2] = theme->FindSurface(widgettype, "MenuItem", "backDisabled");
00875 
00876         theme->GetProperty(widgettype, "MenuItem", "backmodeNormal", miBkModes[0]);
00877         theme->GetProperty(widgettype, "MenuItem", "backmodeSelected", miBkModes[1]);
00878         theme->GetProperty(widgettype, "MenuItem", "backmodeDisabled", miBkModes[2]);
00879 
00880         theme->GetProperty(widgettype, "MenuItem", "blendNormal", miBlends[0]);
00881         theme->GetProperty(widgettype, "MenuItem", "blendSelected", miBlends[1]);
00882         theme->GetProperty(widgettype, "MenuItem", "blendDisabled", miBlends[2]);
00883 }
00884 
00885 void PG_PopupMenu::LoadThemeStyle(const std::string& widgettype, const std::string& objectname) {
00886         PG_ThemeWidget::LoadThemeStyle(widgettype, objectname);
00887 }
00888 
00889 void PG_PopupMenu::eventMouseEnter() {
00890         PG_ThemeWidget::eventMouseEnter();
00891 }
00892 
00893 void PG_PopupMenu::eventMouseLeave() {
00894         PG_ThemeWidget::eventMouseLeave();
00895 }
00896 
00897 bool PG_PopupMenu::SetMenuItemSlot(int id, MenuItem::MenuItemSlot slot, PG_Pointer clientdata) {
00898         MII it;
00899         PG_PopupMenu::MenuItem* item;
00900         int itid;
00901 
00902         it=items.begin();
00903         while(it!=items.end()) {
00904 
00905                 itid=(*it)->getId();
00906 
00907                 if(id==itid) {
00908                         item=*it;
00909                         item->sigSelectMenuItem.connect(slot, clientdata);
00910                         return true;
00911                 }
00912                 it++;
00913         }
00914         return false;
00915 }

Generated on Tue Jun 24 01:27:48 2008 for Advanced Strategic Command by  doxygen 1.4.2