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 #include <pgmultilineedit.h>
00023 
00024 #include "cargowidget.h"
00025 #include "../containerbase.h"
00026 #include "../iconrepository.h"
00027 #include "../vehicle.h"
00028 #include "../gamemap.h"
00029 #include "../graphics/blitter.h"
00030 #include "../graphics/drawing.h"
00031 #include "../widgets/bargraphwidget.h"
00032 #include "../paradialog.h"
00033 #include "../gameoptions.h"
00034 #include "../events.h"
00035 
00036 HighLightingManager::HighLightingManager() : marked(0) {};
00037 
00038 int HighLightingManager::getMark()
00039 {
00040    return marked;
00041 };
00042 
00043 void HighLightingManager::setNew(int pos )
00044 {
00045    int old = marked;
00046    marked = pos;
00047    markChanged(old,pos);
00048 };
00049 
00050 
00051 
00052 void StoringPosition :: markChanged(int old, int mark)
00053 {
00054    if ( num == old || num == mark )
00055       Redraw();
00056 }
00057 
00058 
00059 
00060 
00061 int StoringPosition :: spWidth = -1;
00062 int StoringPosition :: spHeight = -1;
00063 
00064 PG_Rect StoringPosition :: CalcSize( const PG_Point& pos  )
00065 {
00066    if ( spWidth < 0 ) {
00067       Surface& icon = IconRepository::getIcon( "hexfield-bld-1.png" );
00068       spWidth = icon.w();
00069       spHeight = icon.h();
00070    }
00071 
00072    return PG_Rect( pos.x, pos.y, spWidth, spHeight );
00073 }
00074 
00075 
00076 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  )
00077       : PG_Widget ( parent, CalcSize(pos), true ), highlight( highLightingManager ), storage( storageVector), num(number), regular(regularPosition), unitPosition( unitPos ), dragState( Off ), dragTarget( NoDragging )
00078 {
00079    highlight.markChanged.connect( SigC::slot( *this, &StoringPosition::markChanged ));
00080    highlight.redrawAll.connect( SigC::bind( SigC::slot( *this, &StoringPosition::Redraw), true));
00081 
00082    if ( unitPosition.x < 0 ) {
00083       unitPosition.x = (Width() - fieldsizex)/2;
00084       unitPosition.y = (Height() - fieldsizey)/2;
00085    }
00086 
00087    clippingSurface = Surface::createSurface( spWidth + 10, spHeight + 10, 32, 0 );
00088    
00089    
00090    this->cargoWidget = cargoWidget;
00091 }
00092 
00093 void StoringPosition::setBargraphValue( const ASCString& widgetName, float fraction )
00094 {
00095    BarGraphWidget* bgw = dynamic_cast<BarGraphWidget*>( FindChild( widgetName, true ) );
00096    if ( bgw )
00097       bgw->setFraction( fraction );
00098 }
00099 
00100 void StoringPosition::setLabelText ( const ASCString& widgetName, const ASCString& text, PG_Widget* parent )
00101 {
00102    if ( !parent )
00103       parent = this;
00104 
00105    PG_Label* l = dynamic_cast<PG_Label*>( parent->FindChild( widgetName, true ) );
00106    if ( l )
00107       l->SetText( text );
00108    else {
00109       PG_LineEdit* l = dynamic_cast<PG_LineEdit*>( parent->FindChild( widgetName, true ) );
00110       if ( l )
00111          l->SetText( text );
00112       else {
00113          PG_MultiLineEdit* l = dynamic_cast<PG_MultiLineEdit*>( parent->FindChild( widgetName, true ) );
00114          if ( l )
00115             l->SetText( text );
00116       }
00117    }
00118 }
00119 
00120 
00121 void StoringPosition :: eventBlit (SDL_Surface *surface, const PG_Rect &src, const PG_Rect &dst){
00122    
00123    PG_Draw::BlitSurface( clippingSurface.getBaseSurface(), src, PG_Application::GetScreen(), dst);
00124    
00125 }
00126 
00127 
00128 void StoringPosition :: eventDraw (SDL_Surface *surface, const PG_Rect &src)
00129 {
00130    clippingSurface.FillTransparent();
00131    
00132    ASCString background = "hexfield-bld-";
00133    if ( dragTarget == NoDragging ) {
00134       background += regular ? "1" : "2";
00135       if (  num == highlight.getMark() )
00136          background += "h";
00137    } else {
00138       background += dragTarget==TargetAvail ? "1" : "2";
00139    }
00140    background += ".png";
00141 
00142    Surface& icon = IconRepository::getIcon( background );
00143   
00144    MegaBlitter<4,4,ColorTransform_None, ColorMerger_AlphaMerge> blitter;
00145    blitter.blit( icon, clippingSurface, SPoint(0,0));
00146 
00147    if ( num < storage.size() && storage[num] ) {
00148       int xpos = unitPosition.x;
00149       int ypos = unitPosition.y;
00150       if ( num != highlight.getMark() )
00151          ypos += 1;
00152 
00153 
00154       storage[num]->direction = 0;
00155 
00156       if ( storage[num]->getMovement() > 0  )
00157          storage[num]->paint( clippingSurface, SPoint(xpos,ypos), 0 ); // storage[num]->getOwner() );
00158       else
00159          storage[num]->paint( clippingSurface, SPoint(xpos,ypos), true, 0 ); // storage[num]->getMap()->getNeutralPlayerNum() );
00160 
00161       setBargraphValue( "DamageBar", float(100-storage[num]->damage)/100 );
00162 
00163       if ( storage[num]->getStorageCapacity().fuel ) {
00164          float f = float(storage[num]->getResource( maxint, 2, true, 0 )) / storage[num]->getStorageCapacity().fuel;
00165          setBargraphValue( "FuelBar", f );
00166       } else
00167          setBargraphValue( "FuelBar", 0 );
00168 
00169       if ( storage[num]->getStorageCapacity().material ) {
00170          float f = float(storage[num]->getResource( maxint, 1, true, 0 )) / storage[num]->getStorageCapacity().material;
00171          setBargraphValue( "MaterialBar", f );
00172       } else
00173          setBargraphValue( "MaterialBar", 0 );
00174 
00175 
00176       if ( storage[num]->typ->maxLoadableWeight ) {
00177          float f = float(storage[num]->cargoWeight()) / storage[num]->typ->maxLoadableWeight;
00178          setBargraphValue( "CargoBar", f );
00179       } else
00180          setBargraphValue( "CargoBar", 0 );
00181 
00182       setLabelText( "SlotUnitName", storage[num]->name );
00183          
00184       ContainerBase* container = storage[num];
00185       
00186       int slots = 0;
00187       for ( ContainerBase::Cargo::const_iterator i = container->getCargo().begin(); i != container->getCargo().end(); ++i )
00188          if( *i )
00189             ++slots;
00190                
00191       if ( container->baseType->maxLoadableUnits ) {
00192          float f = float( slots ) / float(container->baseType->maxLoadableUnits);
00193          setBargraphValue ( "SlotBar", f );
00194       } else
00195          setBargraphValue ( "SlotBar", 0 );
00196       
00197       
00198       setLabelText( "Weight",ASCString::toString( storage[num]->weight() ));
00199       
00200       
00201       ASCString s;
00202       if ( container->baseType->maxLoadableUnits )
00203          s.format( "%d / %d", container->cargoWeight(), container->baseType->maxLoadableWeight );
00204       else
00205          s = "-";
00206       setLabelText( "CargoUsage", s );
00207    
00208       s.format( "%d / %d", slots, container->baseType->maxLoadableUnits );
00209       setLabelText( "SlotSummary", s );
00210       
00211    } else {
00212       setBargraphValue( "DamageBar", 0 );
00213       setBargraphValue( "FuelBar", 0 );
00214       setBargraphValue( "MaterialBar", 0 );
00215       setBargraphValue( "CargoBar", 0 );
00216       setLabelText( "SlotUnitName", "" );
00217       setBargraphValue ( "SlotBar", 0 );
00218       setLabelText( "CargoUsage", "" );
00219       setLabelText( "SlotSummary", "" );
00220       setLabelText( "Weight", "" );
00221    }
00222 
00223    // PG_Draw::BlitSurface( clippingSurface.getBaseSurface(), src, PG_Application::GetScreen(), dst);
00224 //    PG_Draw::DrawSurface( src, dst);
00225 }
00226 
00227 
00228 bool StoringPosition::eventMouseButtonDown(const SDL_MouseButtonEvent* button)
00229 {
00230    if ( button->type != SDL_MOUSEBUTTONDOWN  )
00231       return false;
00232 
00233    if ( button->button == CGameOptions::Instance()->mouse.fieldmarkbutton ) {
00234 
00235       int oldPos = highlight.getMark();
00236       highlight.setNew( num );
00237 
00238       highlight.clickOnMarkedUnit( num, SPoint(button->x, button->y), num != oldPos );
00239       return true;
00240    }
00241 
00242 
00243 /*
00244    if ( num >= storage.size() || !storage[num] )
00245       return false;
00246 */
00247 
00248    int x,y;
00249    PG_Application::GetEventSupplier()->GetMouseState(x, y);
00250 
00251 
00252    if ( button->button == CGameOptions::Instance()->mouse.dragndropbutton  && cargoWidget && cargoWidget->dragNdropEnabled() && getUnit() ) {
00253 
00254       SetCapture();
00255       dragState = Pressed;
00256 
00257       dragPointStart.x = x;
00258       dragPointStart.y = y;
00259 
00260       /*
00261 
00262       dragPointOld.x = x;
00263       dragPointOld.y = y;
00264 
00265 
00266       Draging = true;
00267       eventDragStart();
00268       dragimage = eventQueryDragImage();
00269 
00270       if(dragimage != NULL) {
00271       dragimagecache = PG_Draw::CreateRGBSurface(dragimage->w, dragimage->h);
00272       }
00273 
00274       cacheDragArea(dragPointOld); */
00275       return true;
00276    }
00277 
00278    return false;
00279 }
00280 
00281 bool StoringPosition ::eventMouseButtonUp(const SDL_MouseButtonEvent* button)
00282 {
00283    if ( dragState != Off && (button->button != 4 && button->button != 5 )) {
00284       ReleaseCapture();
00285       dragState = Off;
00286 
00287       if ( !cargoWidget )
00288          return false;
00289 
00290       {
00291          // EventHandlingMutex ehm;
00292          
00293          PG_Application::ShowCursor( PG_Application::NONE );
00294          PG_Application::SetCursor( NULL );
00295          PG_Application::ShowCursor( PG_Application::HARDWARE );
00296       }
00297 
00298       int x,y;
00299       PG_Application::GetEventSupplier()->GetMouseState(x, y);
00300 
00301       // x += mouseCursorOffset.x;
00302       // y += mouseCursorOffset.y;
00303 
00304       StoringPosition* s = dynamic_cast<StoringPosition*>( FindWidgetFromPos (x, y));
00305       if ( s )
00306          cargoWidget->releaseDrag( s->getUnit() );
00307       else {
00308          cargoWidget->releaseDrag( x, y);
00309       }
00310 
00311 
00312 
00313       return true;
00314    } else
00315       return false;
00316 }
00317 
00318 #define square(x) ((x)*(x))
00319 
00320 bool StoringPosition::eventMouseMotion (const SDL_MouseMotionEvent *motion)
00321 {
00322    if ( dragState != Off ) {
00323       if ( cargoWidget )
00324          cargoWidget->sigDragInProcess();
00325 
00326       if ( dragState == Pressed ) {
00327          if ( square(motion->x - dragPointStart.x) + square(motion->y - dragPointStart.y) > 9 ) {
00328             cargoWidget->startDrag( storage[num] );
00329             dragState = Dragging;
00330 
00331             static Surface surf;
00332             if ( !surf.valid() ) {
00333                surf = Surface::createSurface( fieldsizex+20, fieldsizey+20, 32 ); // somewhat larger because of potential shadow
00334                mouseCursorOffset = PG_Point( fieldsizex/2, fieldsizey/2);
00335             }
00336             surf.Fill( 0 );
00337 
00338             MegaBlitter<4,4,ColorTransform_None, ColorMerger_AlphaOverwrite> blitter;
00339             blitter.blit( IconRepository::getIcon("mouse.png"), surf, SPoint(0,0));
00340 
00341             // EventHandlingMutex ehm;
00342             
00343             getUnit()->paint( surf, SPoint(0,0), getUnit()->getOwner() );
00344             PG_Application::ShowCursor( PG_Application::NONE );
00345             PG_Application::SetCursor( const_cast<SDL_Surface*>( surf.getBaseSurface() ));
00346             PG_Application::ShowCursor( PG_Application::SOFTWARE );
00347             
00348          }
00349       }
00350    }
00351 
00352    return false;
00353 }
00354 
00355 
00356 Vehicle* StoringPosition :: getUnit()
00357 {
00358    if ( num >= storage.size() || !storage[num] )
00359       return NULL;
00360    else
00361       return storage[num];
00362 }
00363 
00364 
00365 vector<StoringPosition*> StoringPosition :: setup( PG_Widget* parent, ContainerBase* container, HighLightingManager& highLightingManager, int& unitColumnCount )
00366 {
00367    vector<StoringPosition*> storingPositionVector;
00368    if ( parent) {
00369       int x = 0;
00370       int y = 0;
00371       int posNum = container->baseType->maxLoadableUnits;
00372       if ( container->getCargo().size() > posNum )
00373          posNum = container->getCargo().size();
00374 
00375       for ( int i = 0; i < posNum; ++i ) {
00376          StoringPosition* sp = new StoringPosition( parent, PG_Point( x, y), PG_Point(-1,-1), highLightingManager, container->getCargo(), i, container->baseType->maxLoadableUnits >= container->getCargo().size() );
00377          storingPositionVector.push_back( sp );
00378          x += StoringPosition::spWidth;
00379          if ( x + StoringPosition::spWidth >= parent->Width() - 20 ) {
00380             if ( !unitColumnCount )
00381                unitColumnCount = i + 1;
00382             x = 0;
00383             y += StoringPosition::spHeight;
00384          }
00385       }
00386    }
00387    return storingPositionVector;
00388 }
00389 
00390 
00391  
00392 
00393 CargoWidget :: CargoWidget( PG_Widget* parent, const PG_Rect& pos, ContainerBase* container, bool setup ) : PG_ScrollWidget( parent, pos ), dragNdrop(true), unitColumnCount(0), draggedUnit(NULL)
00394 {
00395    this->container = container;
00396    SetTransparency( 255 );
00397 
00398    if ( setup )
00399       registerStoringPositions( StoringPosition::setup( this, container, unitHighLight, unitColumnCount ), unitColumnCount );
00400 
00401    if ( my_objVerticalScrollbar )
00402       my_objVerticalScrollbar->sigScrollTrack.connect ( SigC::slot( *this, &CargoWidget::handleScrollTrack ));
00403 
00404    if ( my_objHorizontalScrollbar )
00405       my_objHorizontalScrollbar->sigScrollTrack.connect ( SigC::slot( *this, &CargoWidget::handleScrollTrack ));
00406 };
00407 
00408 void CargoWidget::registerStoringPositions( vector<StoringPosition*> sp, const int& colCount )
00409 {
00410    unitColumnCount = colCount;
00411    storingPositionVector  = sp;
00412    unitHighLight.markChanged.connect( SigC::slot( *this, &CargoWidget::checkStoringPosition ));
00413    unitHighLight.clickOnMarkedUnit.connect( SigC::slot( *this, &CargoWidget::click ));
00414 }
00415 
00416 bool  CargoWidget::handleScrollTrack (PG_ScrollBar *widget, long data)
00417 {
00418    sigScrollTrack();
00419    return true;
00420 }
00421 
00422 
00423 
00424 void CargoWidget::click( int num, SPoint mousePos, bool first )
00425 {
00426    if ( container->getCargo().size() > num )
00427       unitClicked( container->getCargo()[num], mousePos, first );
00428    else
00429       unitClicked( NULL, mousePos, first );
00430 }
00431 
00432 
00433 void CargoWidget :: redrawAll()
00434 {
00435    BulkGraphicUpdates bgu( this );
00436    unitHighLight.redrawAll();
00437 }
00438 
00439 
00440 void CargoWidget :: moveSelection( int delta )
00441 {
00442    int newpos = unitHighLight.getMark() + delta;
00443 
00444    if ( newpos < 0 )
00445       newpos = 0;
00446 
00447    if ( newpos >= storingPositionVector.size() )
00448       newpos = storingPositionVector.size() -1 ;
00449 
00450    if ( newpos != unitHighLight.getMark() )
00451       unitHighLight.setNew( newpos );
00452 }
00453 
00454 bool CargoWidget :: eventKeyDown(const SDL_KeyboardEvent* key)
00455 {
00456    if ( key->keysym.sym == SDLK_RIGHT )  {
00457       moveSelection(1);
00458       return true;
00459    }
00460    if ( key->keysym.sym == SDLK_LEFT )  {
00461       moveSelection(-1);
00462       return true;
00463    }
00464    if ( key->keysym.sym == SDLK_UP )  {
00465       moveSelection(-unitColumnCount);
00466       return true;
00467    }
00468    if ( key->keysym.sym == SDLK_DOWN )  {
00469       moveSelection(unitColumnCount);
00470       return true;
00471    }
00472    return false;
00473 };
00474 
00475 
00476 void CargoWidget :: checkStoringPosition( int oldpos, int newpos )
00477 {
00478 //  PG_Widget* unitScrollAreaw = dynamic_cast<PG_Widget*>(FindChild( "UnitScrollArea", true ));
00479 //  PG_ScrollWidget* unitScrollArea = dynamic_cast<PG_ScrollWidget*>(FindChild( "UnitScrollArea", true ));
00480 //  if ( unitScrollArea )
00481    if ( newpos < storingPositionVector.size() && newpos >= 0 )
00482       ScrollToWidget( storingPositionVector[newpos] );
00483 
00484    unitMarked( getMarkedUnit() );
00485 }
00486 
00487 Vehicle* CargoWidget :: getMarkedUnit()
00488 {
00489    int pos = unitHighLight.getMark();
00490    if ( !container || pos < 0 || pos >= container->getCargo().size() )
00491       return NULL;
00492    else
00493       return container->getCargo()[pos];
00494 }
00495 
00496 
00497 void CargoWidget :: startDrag( Vehicle* v )
00498 {
00499    for ( StoringPositionVector::iterator i = storingPositionVector.begin(); i != storingPositionVector.end(); ++i ) {
00500       Vehicle* target = (*i)->getUnit();
00501       if ( target && target != v && sigDragAvail( v, target ) ) {
00502          (*i)->setDragTarget( StoringPosition::TargetAvail );
00503       } else {
00504          (*i)->setDragTarget( StoringPosition::TargetNotAvail );
00505       }
00506       draggedUnit = v;
00507    }
00508    Redraw();
00509 }
00510 
00511 void CargoWidget :: releaseDrag( Vehicle* v)
00512 {
00513    for ( StoringPositionVector::iterator i = storingPositionVector.begin(); i != storingPositionVector.end(); ++i )
00514       (*i)->setDragTarget( StoringPosition::NoDragging );
00515 
00516    if ( v )
00517       sigDragDone( draggedUnit, v );
00518    else
00519       sigDragAborted();
00520 
00521    draggedUnit = NULL;
00522 }
00523 
00524 void CargoWidget :: releaseDrag( int x, int y )
00525 {
00526    for ( StoringPositionVector::iterator i = storingPositionVector.begin(); i != storingPositionVector.end(); ++i )
00527       (*i)->setDragTarget( StoringPosition::NoDragging );
00528 
00529    if ( IsMouseInside() )
00530       sigDragAborted();
00531    else
00532       sigDragDone( draggedUnit, NULL );
00533 
00534    draggedUnit = NULL;
00535 }

Generated on Mon May 21 01:26:29 2012 for Advanced Strategic Command by  doxygen 1.5.1