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

guiiconhandler.cpp

Go to the documentation of this file.
00001 
00005 /*
00006     This file is part of Advanced Strategic Command; http://www.asc-hq.de
00007     Copyright (C) 1994-2003  Martin Bickel  and  Marc Schellenberger
00008 
00009     This program is free software; you can redistribute it and/or modify
00010     it under the terms of the GNU General Public License as published by
00011     the Free Software Foundation; either version 2 of the License, or
00012     (at your option) any later version.
00013 
00014     This program is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017     GNU General Public License for more details.
00018 
00019     You should have received a copy of the GNU General Public License
00020     along with this program; see the file COPYING. If not, write to the
00021     Free Software Foundation, Inc., 59 Temple Place, Suite 330,
00022     Boston, MA  02111-1307  USA
00023 */
00024 
00025 #include <stdio.h>
00026 #include <cstring>
00027 #include <stdlib.h>
00028 #include <SDL_image.h>
00029 
00030 #include "guiiconhandler.h"
00031 #include "spfst.h"
00032 #include "iconrepository.h"
00033 #include "mapdisplay.h"
00034 #include "sigc++/retype_return.h"
00035 #include "asc-mainscreen.h"
00036 #include "gameoptions.h"
00037 
00038 const int guiIconSizeX = 49;
00039 const int guiIconSizeY = 35;
00040 const int guiIconSpace = 5;
00041 const int guiIconColumnNum = 3;
00042 
00043 
00044 const int smallGuiIconSizeX = 30;
00045 const int smallGuiIconSizeY = 22;
00046 const int smallGuiIconSpace = 2;
00047 const float smallGuiIconSizeFactor = 0.6;
00048 
00049 
00050 GuiButton::GuiButton( PG_Widget *parent, const PG_Rect &r ) : PG_Button( parent, r, "", -1, "GuiButton"), func( NULL ), id(-1)
00051 {
00052   sigClick.connect ( SigC::slot( *this, &GuiButton::exec ));
00053   SetBackground( PRESSED, IconRepository::getIcon("empty-pressed.png").getBaseSurface() );
00054   SetBackground( HIGHLITED, IconRepository::getIcon("empty-high.png").getBaseSurface() );
00055   SetBackground( UNPRESSED, IconRepository::getIcon("empty.png").getBaseSurface() );
00056   SetBorderSize(0,0,0);
00057 }
00058 
00059 bool GuiButton::exec()
00060 {
00061   if ( func ) {
00062      func->execute( pos, subject, id );
00063      return true;
00064   }
00065   return false;
00066 }
00067 
00068 
00069 void GuiButton::registerFunc( GuiFunction* f, const MapCoordinate& position, ContainerBase* subject, int id )
00070 {
00071    this->id = id;
00072    this->subject = subject;
00073    func = f;
00074    pos = position;
00075    SetIcon( f->getImage( position, subject, id).getBaseSurface());
00076 }
00077 
00078 void GuiButton::unregisterFunc()
00079 {
00080    func = NULL;
00081    id = 0;
00082    subject = NULL;
00083    pos = MapCoordinate(-1,-1);
00084    SetIcon ( (SDL_Surface*) NULL );
00085 }
00086 
00087 void GuiButton::eventMouseEnter()
00088 {
00089    PG_Button::eventMouseEnter();
00090    showInfoText();
00091 }
00092 
00093 void GuiButton::eventMouseLeave()
00094 {
00095    PG_Button::eventMouseLeave();
00096    MessagingHub::Instance().statusInformation("");
00097 }
00098 
00099 bool GuiButton::checkForKey( const SDL_KeyboardEvent* key, int modifier )
00100 {
00101    if ( func->available( pos, subject, id ))
00102       if ( func->checkForKey( key, modifier, id)) {
00103          func->execute( pos, subject, id );
00104          return true;
00105       }
00106    return false;
00107 }
00108 
00109 void GuiButton::showInfoText()
00110 {
00111    if ( func )
00112       MessagingHub::Instance().statusInformation( func->getName(pos, subject, id));
00113 }
00114 
00115 
00116 
00117 SmallGuiButton::SmallGuiButton( PG_Widget *parent, const PG_Rect &r, GuiButton* guiButton, NewGuiHost* host ) : PG_Button( parent, r, "", -1, "GuiButton"), referenceButton( guiButton )
00118 {
00119   sigClick.connect ( SigC::slot( *host, &NewGuiHost::clearSmallIcons ));
00120   sigClick.connect ( SigC::slot( *guiButton, &GuiButton::exec ));
00121 
00122   SetBackground( PRESSED, IconRepository::getIcon("empty-small-pressed.png").getBaseSurface() );
00123   SetBackground( HIGHLITED, IconRepository::getIcon("empty-small-high.png").getBaseSurface() );
00124   SetBackground( UNPRESSED, IconRepository::getIcon("empty-small.png").getBaseSurface() );
00125   SetBorderSize(0,0,0);
00126   SetDirtyUpdate(true);
00127 
00128   SetBehaviour( SIGNALONRELEASE );
00129 
00130   updateIcon();
00131 }
00132 
00133 
00134 void SmallGuiButton::updateIcon()
00135 {
00136    SDL_Surface* icn = referenceButton->GetIcon( UNPRESSED );
00137    if ( icn ) {
00138       smallIcon = PG_Draw::ScaleSurface( icn, smallGuiIconSizeFactor, smallGuiIconSizeFactor );
00139       SetIcon( smallIcon, NULL, NULL, true );
00140    } else
00141       smallIcon = NULL;
00142 }
00143 
00144 
00145 
00146 void SmallGuiButton::press()
00147 {
00148    SetPressed(true);
00149    Update();
00150 }   
00151 
00152 void SmallGuiButton::showInfoText()
00153 {
00154    if ( referenceButton && referenceButton->func )
00155       MessagingHub::Instance().statusInformation( referenceButton->func->getName(referenceButton->pos, referenceButton->subject, referenceButton->id));
00156 }
00157 
00158 
00159 void SmallGuiButton::eventMouseEnter()
00160 {
00161    PG_Button::eventMouseEnter();
00162    showInfoText();
00163 }
00164 
00165 void SmallGuiButton::eventMouseLeave()
00166 {
00167    PG_Button::eventMouseLeave();
00168    MessagingHub::Instance().statusInformation("");
00169 }
00170 
00171 
00172 SmallGuiButton::~SmallGuiButton()
00173 {
00174 }
00175 
00176 
00177 
00178 void GuiIconHandler::eval( const MapCoordinate& pos, ContainerBase* subject )
00179 {
00180    int num = 0;
00181    for ( Functions::iterator i = functions.begin(); i != functions.end(); ++i ) {
00182       if ( (*i)->available(pos, subject, 0 )) {
00183          GuiButton* b = host->getButton(num);
00184          b->registerFunc( *i, pos, subject, 0 );
00185          b->Show();
00186          ++num;
00187       }
00188    }
00189 
00190    host->disableButtons(num);
00191 }
00192 
00193 /*
00194 void GuiIconHandler::eval()
00195 {
00196    MapCoordinate mc = actmap->getCursor();
00197 
00198    if ( !mc.valid() )
00199       return;
00200 
00201    if ( mc.x >= actmap->xsize || mc.y >= actmap->ysize )
00202       return;
00203 
00204    ContainerBase* subject = actmap->getField(mc)->getContainer();
00205    
00206    eval( mc, subject );
00207 }
00208 */
00209 
00210 bool GuiIconHandler::checkForKey( const SDL_KeyboardEvent* key, int modifier )
00211 {
00212 #if 0
00213    if ( !actmap->getCursor().valid())
00214       return false;
00215 
00216    ContainerBase* subject = actmap->getField(actmap->getCursor())->getContainer();
00217    
00218    for ( Functions::iterator i = functions.begin(); i != functions.end(); ++i )
00219       if ( (*i)->available(actmap->getCursor(), subject, 0 ))
00220          if ( (*i)->checkForKey( key, modifier, 0)) {
00221             (*i)->execute(actmap->getCursor(), subject, 0 );
00222             return true;
00223          }
00224 #endif         
00225    return false;
00226 }
00227 
00228 
00229 void GuiIconHandler::registerUserFunction( GuiFunction* function )
00230 {
00231    functions.push_back ( function );
00232 }
00233 
00234 
00235 GuiIconHandler::~GuiIconHandler()
00236 {
00237    for ( Functions::iterator i = functions.begin(); i != functions.end(); ++i )
00238       delete *i;
00239 
00240 }
00241 
00242 
00243 
00244 
00245 
00246 NewGuiHost* NewGuiHost::theGuiHost = NULL;
00247 
00248 NewGuiHost :: NewGuiHost (MainScreenWidget *parent, MapDisplayPG* mapDisplay, const PG_Rect &r )
00249          : DashboardPanel( parent, r, "GuiIcons", false ) , handler(NULL), enterKeyPressed(false), keyPressedButton(-1)
00250 {
00251    this->mapDisplay = mapDisplay;
00252    mapDisplay->mouseButtonOnField.connect( SigC::slot( *this, &NewGuiHost::mapIconProcessing ));
00253    updateFieldInfo.connect ( SigC::slot( *this, &NewGuiHost::evalCursor ));
00254    theGuiHost = this;
00255 
00256    cursorMoved.connect( SigC::hide_return( SigC::slot( *this, &NewGuiHost::clearSmallIcons )) );
00257 
00258    
00259    PG_Application::GetApp()->sigKeyDown.connect( SigC::slot( *this, &NewGuiHost::eventKeyDown ));
00260    PG_Application::GetApp()->sigKeyUp.connect( SigC::slot( *this, &NewGuiHost::eventKeyUp ));
00261    SetTransparency(255);
00262    
00263    parent->lockOptionsChanged.connect( SigC::slot( *this, &NewGuiHost::lockOptionsChanged ));
00264 
00265    GameMap::sigMapDeletion.connect( SigC::slot( *this, &NewGuiHost::mapDeleted ));
00266 }
00267 
00268 void NewGuiHost::lockOptionsChanged( int options )
00269 {
00270    if ( options & MainScreenWidget::LockOptions::MapActions )  
00271       // EnableReceiver(false, true);
00272       Hide();
00273    else  
00274       // EnableReceiver(true, true);
00275       Show();
00276 }
00277 
00278 
00279 class SmallButtonHolder : public SpecialInputWidget {
00280       bool locked;
00281    public:
00282       void Lock() { SetCapture(); locked = true; };
00283       void Unlock() { ReleaseCapture(); locked = false; };
00284 
00285       SmallButtonHolder (PG_Widget *parent, const PG_Rect &rect ) : SpecialInputWidget( parent, rect ), locked(false) {};
00286       bool eventMouseMotion (const SDL_MouseMotionEvent *motion) { return true; };
00287       bool eventMouseButtonDown (const SDL_MouseButtonEvent *button) { return true; };
00288       bool eventMouseButtonUp (const SDL_MouseButtonEvent *button) { Unlock(); return true; };
00289       
00290       bool ProcessEvent(const SDL_Event * event, bool bModal) { return SpecialInputWidget::ProcessEvent( event, bModal ); };
00291       bool ProcessEvent ( const SDL_Event *   event  )
00292       {
00293          /*
00294          PG_RectList* cl = GetChildList ();
00295                    for(PG_Widget* i = cl->first(); i != NULL; i = i->next()) {
00296                            if ( i->ProcessEvent( event, true ))
00297                return true;
00298                    }
00299          */
00300         
00301          bool result = false;
00302          
00303          if ( locked ) 
00304             ReleaseCapture();
00305          
00306          if ( SpecialInputWidget::ProcessEvent( event, true )) 
00307             result = true;
00308          
00309          if ( locked )
00310             SetCapture();
00311              
00312          if ( !result && event->type == SDL_MOUSEBUTTONUP )
00313             Unlock();
00314          
00315          return result;
00316       }
00317 
00318 };
00319 
00320 
00321 
00322 SmallButtonHolder* NewGuiHost :: smallButtonHolder = NULL;
00323 
00324 
00325 void NewGuiHost::evalCursor()
00326 {
00327    if ( !actmap )
00328       return;
00329    
00330    MapCoordinate mc = actmap->getCursor();
00331 
00332    if ( !mc.valid() )
00333       return;
00334 
00335    if ( mc.x >= actmap->xsize || mc.y >= actmap->ysize )
00336       return;
00337 
00338    ContainerBase* subject = actmap->getField(mc)->getContainer();
00339    
00340    eval( mc, subject );
00341 }
00342 
00343 void NewGuiHost::mapDeleted( GameMap& map )
00344 {
00345    /*
00346    while ( theGuiHost->iconHandlerStack.size() >= 1 )
00347       popIconHandler();
00348       */
00349 }
00350 
00351 
00352 void NewGuiHost::eval( const MapCoordinate& pos, ContainerBase* subject )
00353 {
00354    if ( handler ) {
00355       BulkGraphicUpdates bgu(this);
00356       handler->eval( pos, subject );
00357    }
00358 }
00359 
00360 
00361 void NewGuiHost::pushIconHandler( GuiIconHandler* iconHandler )
00362 {
00363    if ( !theGuiHost )
00364       return;
00365 
00366    if ( theGuiHost->handler )
00367       theGuiHost->iconHandlerStack.push_back( theGuiHost->handler );
00368 
00369    theGuiHost->handler = iconHandler;
00370    iconHandler->registerHost( theGuiHost );
00371    updateFieldInfo();
00372 }
00373 
00374 GuiIconHandler* NewGuiHost::getIconHandler(  )
00375 {
00376    if ( theGuiHost )
00377       return theGuiHost->handler;
00378    else
00379       return NULL;
00380 }
00381 
00382 
00383 void NewGuiHost::popIconHandler( )
00384 {
00385    if ( !theGuiHost )
00386       return;
00387 
00388    theGuiHost->clearSmallIcons();
00389 
00390    assert( theGuiHost->handler );
00391 
00392    theGuiHost->handler->registerHost( NULL );
00393 
00394    theGuiHost->handler = theGuiHost->iconHandlerStack.back();
00395    theGuiHost->iconHandlerStack.pop_back();
00396    updateFieldInfo();
00397 }
00398 
00399 
00400 GuiButton* NewGuiHost::getButton( int i )
00401 {
00402    while ( i >= buttons.size() ) {
00403       int w = (Width() - 4 * guiIconSpace) / guiIconColumnNum;
00404       GuiButton* b = new GuiButton ( this, PG_Rect( guiIconSpace + i%3 * (w + guiIconSpace), 10 + guiIconSpace + i/3 * (guiIconSpace + guiIconSizeY), guiIconSizeX, guiIconSizeY));
00405       buttons.push_back ( b );
00406       b->Hide();
00407    }
00408    return buttons[i];
00409 }
00410 
00411 
00412 void NewGuiHost::disableButtons( int i )
00413 {
00414    for ( int j = i; j < buttons.size(); ++j) {
00415       GuiButton* b = getButton(j);
00416       b->Hide();
00417       b->unregisterFunc();
00418    }
00419 }
00420 
00421 
00422 
00423 bool NewGuiHost::mapIconProcessing( const MapCoordinate& pos, const SPoint& mousePos, bool cursorChanged, int button, int prio )
00424 {
00425    if ( prio > 1 )
00426       return false;
00427     
00428    if ( button != CGameOptions::Instance()->mouse.fieldmarkbutton )
00429       return false;
00430 
00431    
00432 
00433    // PG_Point p = mapDisplay->ScreenToClient( mousePos.x, mousePos.y );
00434    SPoint p = mousePos;
00435 
00436    tfield* fld = actmap->getField(pos);
00437 
00438    bool positionedUnderCursor = false;
00439    if ( ( fld->vehicle || fld->building) && fieldvisiblenow(fld) )
00440       positionedUnderCursor = true;
00441    
00442    if ( fld->a.temp ) {
00443       positionedUnderCursor = true;
00444       cursorChanged = false;
00445    }
00446 
00447    if ( positionedUnderCursor ) {
00448       p.x -= smallGuiIconSizeX/2;
00449       p.y -= smallGuiIconSizeY/2;
00450    } else {
00451       p.x += 2;
00452       p.y += 2;
00453    }
00454 
00455    showSmallIcons( mainScreenWidget, p, cursorChanged );
00456    return true;
00457 }
00458 
00459 
00460 SmallGuiButton* NewGuiHost::getSmallButton( int i )
00461 {
00462    assert(smallButtonHolder);
00463    while ( i >= smallButtons.size() ) {
00464       PG_Rect r = PG_Rect( (smallGuiIconSizeX + smallGuiIconSpace) * smallButtons.size(), 0, smallGuiIconSizeX, smallGuiIconSizeY  );
00465       SmallGuiButton* b = new SmallGuiButton ( smallButtonHolder, r, getButton(i), this);
00466       smallButtons.push_back ( b );
00467       b->Hide();
00468    }
00469 
00470    return smallButtons[i];
00471 }
00472 
00473 
00474 bool   NewGuiHost::ProcessEvent (const SDL_Event *event, bool bModal)
00475 {
00476    if ( smallButtonHolder && smallButtonHolder->ProcessEvent( event ))
00477       return true;
00478    
00479    if ( DashboardPanel::ProcessEvent( event, bModal ))
00480       return true;
00481 
00482    return false;
00483 }
00484 
00485 
00486 
00487 bool NewGuiHost::showSmallIcons( PG_Widget* parent, const SPoint& pos, bool cursorChanged )
00488 {
00489    clearSmallIcons();
00490 
00491    BulkGraphicUpdates bgu;
00492   
00493    SmallGuiButton* firstSmallButton = NULL;
00494    
00495    int count = 0;
00496    if ( !cursorChanged || CGameOptions::Instance()->mouse.singleClickAction ) {
00497       for ( int j = 0; j < buttons.size(); ++j)
00498          if ( !getButton(j)->IsHidden() )
00499             ++count;
00500       
00501       if ( count ) {
00502          if ( !smallButtonHolder ) 
00503             smallButtonHolder = new SmallButtonHolder ( NULL, PG_Rect::null );
00504          
00505 
00506          smallButtonHolder->MoveWidget( PG_Rect( pos.x, pos.y, count * smallGuiIconSizeX + (count-1)*smallGuiIconSpace, smallGuiIconSizeY ), false );
00507 
00508          for ( int j = 0; j < buttons.size(); ++j) {
00509             GuiButton* b = getButton(j);
00510             if ( !b->IsHidden() ) {
00511                SmallGuiButton* sgi = getSmallButton( j );
00512                sgi->updateIcon();
00513                sgi->SetHidden(false);
00514                if ( j == 0  && sgi->IsMouseInside() )
00515                   firstSmallButton = sgi;
00516             } else
00517                getSmallButton( j )->SetHidden(true);
00518          }
00519       }
00520    }
00521 
00522    bgu.release();
00523    if ( smallButtonHolder && count ) {
00524       smallButtonHolder->BringToFront();
00525       smallButtonHolder->Show();
00526       smallButtonHolder->Lock();
00527 
00528       if ( firstSmallButton ) {
00529          firstSmallButton->press();
00530          firstSmallButton->showInfoText();
00531       }
00532    }
00533    
00534    return true;
00535 }
00536 
00537 
00538 bool NewGuiHost::setNewButtonPressed( int i )
00539 {
00540    if ( keyPressedButton == i )
00541       return false;
00542 
00543    if ( keyPressedButton >= 0 ) {
00544       GuiButton* button = getButton( keyPressedButton );
00545       if ( button ) {
00546          button->SetPressed(false);
00547          button->SetToggle(false);
00548       }
00549    }
00550 
00551    if ( i < buttons.size() || i < 0 ) {
00552       keyPressedButton = i;
00553 
00554       if ( keyPressedButton >= 0 ) {
00555          GuiButton* button = getButton( keyPressedButton );
00556          if ( button ) {
00557             button->SetToggle(true);
00558             button->SetPressed(true);
00559             button->showInfoText();
00560          }
00561       }
00562       return true;
00563    }
00564    return false;
00565 }
00566 
00567 bool NewGuiHost::eventKeyDown(const SDL_KeyboardEvent* key)
00568 {
00569    int mod = SDL_GetModState() & ~(KMOD_NUM | KMOD_CAPS | KMOD_MODE);
00570    if ( mod )
00571       return false;
00572 
00573    if ( !IsVisible() )
00574       return false;
00575 
00576    if ( key->keysym.sym == SDLK_RETURN   ) {
00577       if ( !enterKeyPressed ) {
00578          mapDisplay->keyboadCursorMovement( false );
00579          enterKeyPressed = true;
00580          setNewButtonPressed( 0 );
00581       }
00582       return true;
00583    }
00584 
00585    if ( enterKeyPressed ) {
00586       if ( key->keysym.sym == SDLK_RIGHT  || key->keysym.sym == SDLK_KP6 )
00587          return setNewButtonPressed( keyPressedButton + 1);
00588 
00589       if ( key->keysym.sym == SDLK_LEFT  || key->keysym.sym == SDLK_KP4 )
00590          if  ( keyPressedButton > 0 )
00591             return setNewButtonPressed( keyPressedButton - 1);
00592 
00593       if ( key->keysym.sym == SDLK_UP || key->keysym.sym == SDLK_KP8 )
00594          if ( keyPressedButton >= guiIconColumnNum )
00595             return setNewButtonPressed( keyPressedButton - guiIconColumnNum );
00596 
00597       if ( key->keysym.sym == SDLK_DOWN || key->keysym.sym == SDLK_KP2 )
00598          return setNewButtonPressed( keyPressedButton + guiIconColumnNum );
00599          
00600       if ( key->keysym.sym == SDLK_ESCAPE || key->keysym.sym == SDLK_END ) {
00601          enterKeyPressed = false;
00602          mapDisplay->keyboadCursorMovement( true );
00603          
00604          setNewButtonPressed( -1 );
00605          return true;
00606       }
00607          
00608    } else {
00609       int modifier = SDL_GetModState();
00610       for ( int j = 0; j < buttons.size(); ++j)
00611          if ( getButton(j)->ready() )
00612             if ( getButton(j)->checkForKey( key, modifier ))
00613                return true;
00614 
00615       if ( handler )
00616          if ( handler->checkForKey( key, modifier ))
00617             return true;
00618 
00619    }
00620 
00621    return false;
00622 }
00623 
00624 bool NewGuiHost::eventKeyUp(const SDL_KeyboardEvent* key)
00625 {
00626    if ( key->keysym.sym == SDLK_RETURN  && enterKeyPressed ) {
00627       enterKeyPressed = false;
00628       mapDisplay->keyboadCursorMovement( true );
00629 
00630       GuiButton* button = getButton( keyPressedButton );
00631       if ( button )
00632          button->exec();
00633 
00634       setNewButtonPressed( -1 );
00635       return true;
00636    }
00637 
00638    return false;
00639 }
00640 
00641 
00642 #if 0
00643 
00644 bool NewGuiHost::clearSmallIcons()
00645 {
00646    bool bulk = PG_Application::GetBulkMode();
00647 
00648  //  if ( !bulk )
00649   //    PG_Application::SetBulkMode(true);
00650 
00651    bool redraw;
00652    PG_Rect redrawRect;
00653    if ( smallButtonHolder ) {
00654       redraw = true;
00655       redrawRect = *smallButtonHolder;
00656    } else
00657       redraw = false;
00658    
00659       delete smallButtonHolder;
00660       smallButtonHolder = NULL;
00661 
00662       if ( !bulk ) {
00663     //  PG_Application::SetBulkMode(false);
00664       // mapDisplay->UpdateRect( true );
00665       }
00666 
00667       return true;
00668 }
00669 
00670 #endif
00671 
00672 bool NewGuiHost::clearSmallIcons()
00673 {
00674    if ( smallButtonHolder && smallButtonHolder->IsVisible() ) {
00675       smallButtonHolder->Unlock();
00676       smallButtonHolder->Hide();
00677    }
00678    return true;
00679 }
00680 
00681 
00682 NewGuiHost::~NewGuiHost()
00683 {
00684    if ( handler )
00685       handler->registerHost( NULL );
00686 
00687 }
00688 

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