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 #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 );
00158 else
00159 storage[num]->paint( clippingSurface, SPoint(xpos,ypos), true, 0 );
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
00224
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
00245
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
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
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
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
00302
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 );
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
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
00479
00480
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 }