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

cargowidget.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           cargowidget.cpp  -  description
00003                              -------------------
00004     begin                : Tue Oct 24 2000
00005     copyright            : (C) 2000 by Martin Bickel
00006     email                : bickel@asc-hq.org
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #include <pgimage.h>
00019 #include <pgtooltiphelp.h>
00020 #include <pgapplication.h>
00021 #include <pgeventsupplier.h>
00022 
00023 #include "cargowidget.h"
00024 #include "../containerbase.h"
00025 #include "../iconrepository.h"
00026 #include "../vehicle.h"
00027 #include "../gamemap.h"
00028 #include "../graphics/blitter.h"
00029 #include "../graphics/drawing.h"
00030 #include "../widgets/bargraphwidget.h"
00031 #include "../paradialog.h"
00032 #include "../gameoptions.h"
00033 
00034 
00035 HighLightingManager::HighLightingManager() : marked(0) {};
00036 
00037 int HighLightingManager::getMark()
00038 {
00039    return marked;
00040 };
00041 
00042 void HighLightingManager::setNew(int pos )
00043 {
00044    int old = marked;
00045    marked = pos;
00046    markChanged(old,pos);
00047 };
00048 
00049 
00050 
00051 void StoringPosition :: markChanged(int old, int mark)
00052 {
00053    if ( num == old || num == mark )
00054       Update();
00055 }
00056 
00057 
00058 
00059 
00060 int StoringPosition :: spWidth = -1;
00061 int StoringPosition :: spHeight = -1;
00062 
00063 PG_Rect StoringPosition :: CalcSize( const PG_Point& pos  )
00064 {
00065    if ( spWidth < 0 ) {
00066       Surface& icon = IconRepository::getIcon( "hexfield-bld-1.png" );
00067       spWidth = icon.w();
00068       spHeight = icon.h();
00069    }
00070 
00071    return PG_Rect( pos.x, pos.y, spWidth, spHeight );
00072 }
00073 
00074 
00075 StoringPosition :: StoringPosition( PG_Widget *parent, const PG_Point &pos, const PG_Point& unitPos, HighLightingManager& highLightingManager, const ContainerBase::Cargo& storageVector, int number, bool regularPosition, CargoWidget* cargoWidget  )
00076    : PG_Widget ( parent, CalcSize(pos)), highlight( highLightingManager ), storage( storageVector), num(number), regular(regularPosition), unitPosition( unitPos ), dragState( Off ), dragTarget( NoDragging )
00077 {
00078    highlight.markChanged.connect( SigC::slot( *this, &StoringPosition::markChanged ));
00079    highlight.redrawAll.connect( SigC::bind( SigC::slot( *this, &StoringPosition::Update), true));
00080 
00081    if ( unitPosition.x < 0 ) {
00082       unitPosition.x = (Width() - fieldsizex)/2;
00083       unitPosition.y = (Height() - fieldsizey)/2;
00084    }
00085 
00086    if ( !clippingSurface.valid() )
00087       clippingSurface = Surface::createSurface( spWidth + 10, spHeight + 10, 32, 0 );
00088 
00089    this->cargoWidget = cargoWidget;
00090 }
00091 
00092 void StoringPosition::setBargraphValue( const ASCString& widgetName, float fraction )
00093 {
00094    BarGraphWidget* bgw = dynamic_cast<BarGraphWidget*>( FindChild( widgetName, true ) );
00095    if ( bgw )
00096       bgw->setFraction( fraction );
00097 }
00098 
00099 
00100 void StoringPosition :: eventBlit (SDL_Surface *surface, const PG_Rect &src, const PG_Rect &dst)
00101 {
00102    clippingSurface.Fill(0);
00103 
00104    ASCString background = "hexfield-bld-"; 
00105    if ( dragTarget == NoDragging ) {
00106       background += regular ? "1" : "2";
00107       if (  num == highlight.getMark() )
00108          background += "h";
00109    } else {
00110       background += dragTarget==TargetAvail ? "1" : "2";
00111    }
00112    background += ".png";
00113 
00114    Surface& icon = IconRepository::getIcon( background );
00115 
00116    MegaBlitter<4,4,ColorTransform_None, ColorMerger_AlphaOverwrite> blitter;
00117    blitter.blit( icon, clippingSurface, SPoint(0,0));
00118 
00119    if ( num < storage.size() && storage[num] ) {
00120       int xpos = unitPosition.x;
00121       int ypos = unitPosition.y;
00122       if ( num != highlight.getMark() )
00123          ypos += 1;
00124 
00125       
00126       storage[num]->direction = 0;
00127       
00128       if( storage[num]->getMovement() > 0  )
00129          storage[num]->paint( clippingSurface, SPoint(xpos,ypos), 0 ); // storage[num]->getOwner() );
00130       else
00131          storage[num]->paint( clippingSurface, SPoint(xpos,ypos), true, 0 ); // storage[num]->getMap()->getNeutralPlayerNum() );
00132 
00133       setBargraphValue( "DamageBar", float(100-storage[num]->damage)/100 );
00134 
00135       if ( storage[num]->getStorageCapacity().fuel ) {
00136          float f = float(storage[num]->getResource( maxint, 2, true, 0 )) / storage[num]->getStorageCapacity().fuel;
00137          setBargraphValue( "FuelBar", f );
00138       } else
00139          setBargraphValue( "FuelBar", 0 );
00140  
00141    } else {
00142       setBargraphValue( "DamageBar", 0 );
00143       setBargraphValue( "FuelBar", 0 );
00144    }
00145 
00146    PG_Draw::BlitSurface( clippingSurface.getBaseSurface(), src, PG_Application::GetScreen(), dst);
00147 }
00148 
00149 
00150 bool StoringPosition::eventMouseButtonDown(const SDL_MouseButtonEvent* button) 
00151 {
00152    if ( button->type != SDL_MOUSEBUTTONDOWN  ) 
00153       return false;
00154    
00155    if ( button->button == CGameOptions::Instance()->mouse.fieldmarkbutton ) { 
00156   
00157       int oldPos = highlight.getMark();
00158       highlight.setNew( num );
00159    
00160       highlight.clickOnMarkedUnit( num, SPoint(button->x, button->y), num != oldPos );
00161    }
00162    
00163    
00164    
00165    if ( num >= storage.size() || !storage[num] )
00166       return true;
00167    
00168    
00169         int x,y;
00170         PG_Application::GetEventSupplier()->GetMouseState(x, y);
00171 
00172    
00173    if ( button->button == CGameOptions::Instance()->mouse.dragndropbutton  && cargoWidget && cargoWidget->dragNdropEnabled() && getUnit() ) {
00174       
00175                 SetCapture();
00176       dragState = Pressed;
00177       
00178       dragPointStart.x = x;
00179       dragPointStart.y = y;
00180       
00181       /*
00182 
00183                 dragPointOld.x = x;
00184                 dragPointOld.y = y;
00185 
00186 
00187                 Draging = true;
00188                 eventDragStart();
00189                 dragimage = eventQueryDragImage();
00190 
00191                 if(dragimage != NULL) {
00192                         dragimagecache = PG_Draw::CreateRGBSurface(dragimage->w, dragimage->h);
00193                 }
00194 
00195       cacheDragArea(dragPointOld); */
00196    }
00197 
00198         return true;
00199 }
00200 
00201 bool StoringPosition ::eventMouseButtonUp(const SDL_MouseButtonEvent* button) 
00202 {
00203    if ( dragState != Off ) {
00204       ReleaseCapture();
00205       dragState = Off;
00206       
00207       if ( !cargoWidget )
00208          return false;
00209 
00210       PG_Application::ShowCursor( PG_Application::HARDWARE );
00211 
00212       int x,y;
00213       PG_Application::GetEventSupplier()->GetMouseState(x, y);
00214       
00215       // x += mouseCursorOffset.x;
00216       // y += mouseCursorOffset.y;
00217       
00218       StoringPosition* s = dynamic_cast<StoringPosition*>( FindWidgetFromPos (x, y));
00219       if ( s )
00220          cargoWidget->releaseDrag( s->getUnit() );
00221       else {
00222          cargoWidget->releaseDrag( x, y);
00223       }
00224 
00225       
00226       
00227       return true;
00228    } else
00229       return false;
00230 }
00231 
00232 #define square(x) ((x)*(x))
00233 
00234 bool StoringPosition::eventMouseMotion (const SDL_MouseMotionEvent *motion)
00235 {
00236    if ( dragState != Off ) { 
00237       if ( cargoWidget )
00238          cargoWidget->sigDragInProcess();
00239       
00240       if ( dragState == Pressed ) {
00241          if ( square(motion->x - dragPointStart.x) + square(motion->y - dragPointStart.y) > 9 ) {
00242             cargoWidget->startDrag( storage[num] );
00243             dragState = Dragging;
00244       
00245             static Surface surf;
00246             if ( !surf.valid() ) {
00247                surf = Surface::createSurface( fieldsizex+20, fieldsizey+20, 32 ); // somewhat larger because of potential shadow
00248                mouseCursorOffset = PG_Point( fieldsizex/2, fieldsizey/2);
00249             }
00250             surf.Fill( 0 );
00251             
00252             MegaBlitter<4,4,ColorTransform_None, ColorMerger_AlphaOverwrite> blitter;
00253             blitter.blit( IconRepository::getIcon("mouse.png"), surf, SPoint(0,0));
00254             
00255             getUnit()->paint( surf, SPoint(0,0), getUnit()->getOwner() );
00256             PG_Application::SetCursor( const_cast<SDL_Surface*>( surf.getBaseSurface() ));
00257             PG_Application::ShowCursor( PG_Application::SOFTWARE );
00258          }
00259       }
00260    }
00261   
00262    return false;
00263 }
00264 
00265 
00266 Vehicle* StoringPosition :: getUnit()
00267 {
00268    if ( num >= storage.size() || !storage[num] )
00269       return NULL;
00270    else
00271       return storage[num];
00272 }
00273 
00274 
00275 vector<StoringPosition*> StoringPosition :: setup( PG_Widget* parent, ContainerBase* container, HighLightingManager& highLightingManager, int& unitColumnCount )
00276 {
00277    vector<StoringPosition*> storingPositionVector;
00278    if ( parent) {
00279       int x = 0;
00280       int y = 0;
00281       int posNum = container->baseType->maxLoadableUnits;
00282       if ( container->getCargo().size() > posNum )
00283          posNum = container->getCargo().size();
00284 
00285       for ( int i = 0; i < posNum; ++i ) {
00286          StoringPosition* sp = new StoringPosition( parent, PG_Point( x, y), PG_Point(-1,-1), highLightingManager, container->getCargo(), i, container->baseType->maxLoadableUnits >= container->getCargo().size() );
00287          storingPositionVector.push_back( sp );
00288          x += StoringPosition::spWidth;
00289          if ( x + StoringPosition::spWidth >= parent->Width() - 20 ) {
00290             if ( !unitColumnCount )
00291                unitColumnCount = i + 1;
00292             x = 0;
00293             y += StoringPosition::spHeight;
00294          }
00295       }
00296    }
00297    return storingPositionVector;
00298 }
00299 
00300 
00301 Surface StoringPosition::clippingSurface;
00302 
00303 
00304 
00305 
00306 CargoWidget :: CargoWidget( PG_Widget* parent, const PG_Rect& pos, ContainerBase* container, bool setup ) : PG_ScrollWidget( parent, pos ), dragNdrop(true), unitColumnCount(0), draggedUnit(NULL)
00307 {
00308    this->container = container;
00309    SetTransparency( 255 );
00310 
00311    if ( setup ) 
00312       registerStoringPositions( StoringPosition::setup( this, container, unitHighLight, unitColumnCount ), unitColumnCount );
00313 
00314    if ( my_objVerticalScrollbar )
00315       my_objVerticalScrollbar->sigScrollTrack.connect ( SigC::slot( *this, &CargoWidget::handleScrollTrack ));
00316 
00317    if ( my_objHorizontalScrollbar )
00318       my_objHorizontalScrollbar->sigScrollTrack.connect ( SigC::slot( *this, &CargoWidget::handleScrollTrack ));
00319 };
00320 
00321 void CargoWidget::registerStoringPositions( vector<StoringPosition*> sp, const int& colCount )
00322 {
00323    unitColumnCount = colCount;
00324    storingPositionVector  = sp;
00325    unitHighLight.markChanged.connect( SigC::slot( *this, &CargoWidget::checkStoringPosition ));
00326    unitHighLight.clickOnMarkedUnit.connect( SigC::slot( *this, &CargoWidget::click ));
00327 }
00328 
00329 bool    CargoWidget::handleScrollTrack (PG_ScrollBar *widget, long data)
00330 {
00331    sigScrollTrack();
00332    return true;
00333 }
00334 
00335 
00336 
00337 void CargoWidget::click( int num, SPoint mousePos, bool first )
00338 {
00339    if ( container->getCargo().size() > num )
00340       unitClicked( container->getCargo()[num], mousePos, first );
00341    else
00342       unitClicked( NULL, mousePos, first );
00343 }
00344 
00345 
00346 void CargoWidget :: redrawAll()
00347 {
00348    unitHighLight.redrawAll();
00349 }
00350 
00351 
00352 void CargoWidget :: moveSelection( int delta )
00353 {
00354    int newpos = unitHighLight.getMark() + delta;
00355 
00356    if ( newpos < 0 )
00357       newpos = 0;
00358 
00359    if ( newpos >= storingPositionVector.size() )
00360       newpos = storingPositionVector.size() -1 ;
00361 
00362    if ( newpos != unitHighLight.getMark() )
00363       unitHighLight.setNew( newpos );
00364 }
00365 
00366 bool CargoWidget :: eventKeyDown(const SDL_KeyboardEvent* key)
00367 {
00368    if ( key->keysym.sym == SDLK_RIGHT )  {
00369       moveSelection(1);
00370       return true;
00371    }
00372    if ( key->keysym.sym == SDLK_LEFT )  {
00373       moveSelection(-1);
00374       return true;
00375    }
00376    if ( key->keysym.sym == SDLK_UP )  {
00377       moveSelection(-unitColumnCount);
00378       return true;
00379    }
00380    if ( key->keysym.sym == SDLK_DOWN )  {
00381       moveSelection(unitColumnCount);
00382       return true;
00383    }
00384    return false;
00385 };
00386 
00387 
00388 void CargoWidget :: checkStoringPosition( int oldpos, int newpos )
00389 {
00390    PG_ScrollWidget* unitScrollArea = dynamic_cast<PG_ScrollWidget*>(FindChild( "UnitScrollArea", true ));
00391    if ( unitScrollArea )
00392       if ( newpos < storingPositionVector.size() && newpos >= 0 )
00393          unitScrollArea->ScrollToWidget( storingPositionVector[newpos] );
00394 
00395    unitMarked( getMarkedUnit() );
00396 }
00397 
00398 Vehicle* CargoWidget :: getMarkedUnit()
00399 {
00400    int pos = unitHighLight.getMark();
00401    if ( !container || pos < 0 || pos >= container->getCargo().size() )
00402       return NULL;
00403    else
00404       return container->getCargo()[pos];
00405 }
00406 
00407 
00408 void CargoWidget :: startDrag( Vehicle* v )
00409 {
00410    for ( StoringPositionVector::iterator i = storingPositionVector.begin(); i != storingPositionVector.end(); ++i ) {
00411       Vehicle* target = (*i)->getUnit();
00412       if ( target && target != v && sigDragAvail( v, target ) ) {
00413          (*i)->setDragTarget( StoringPosition::TargetAvail );
00414       } else {
00415          (*i)->setDragTarget( StoringPosition::TargetNotAvail );
00416       }
00417       draggedUnit = v;
00418    }
00419    Update();
00420 }
00421 
00422 void CargoWidget :: releaseDrag( Vehicle* v)
00423 {
00424    for ( StoringPositionVector::iterator i = storingPositionVector.begin(); i != storingPositionVector.end(); ++i ) 
00425       (*i)->setDragTarget( StoringPosition::NoDragging );
00426    
00427    if ( v )
00428       sigDragDone( draggedUnit, v );
00429    else
00430       sigDragAborted();
00431    
00432    draggedUnit = NULL;
00433 }
00434 
00435 void CargoWidget :: releaseDrag( int x, int y )
00436 {
00437    for ( StoringPositionVector::iterator i = storingPositionVector.begin(); i != storingPositionVector.end(); ++i ) 
00438       (*i)->setDragTarget( StoringPosition::NoDragging );
00439    
00440    if ( IsMouseInside() )
00441       sigDragAborted();
00442    else
00443       sigDragDone( draggedUnit, NULL );
00444    
00445    draggedUnit = NULL;
00446 }

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