00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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 );
00130 else
00131 storage[num]->paint( clippingSurface, SPoint(xpos,ypos), true, 0 );
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
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
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
00216
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 );
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 }