Advanced Strategic Command
cargowidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  cargowidget.cpp - description
3  -------------------
4  begin : Tue Oct 24 2000
5  copyright : (C) 2000 by Martin Bickel
6  email : bickel@asc-hq.org
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include <pgimage.h>
19 #include <pgtooltiphelp.h>
20 #include <pgapplication.h>
21 #include <pgeventsupplier.h>
22 #include <pgmultilineedit.h>
23 
24 #include "cargowidget.h"
25 #include "../containerbase.h"
26 #include "../iconrepository.h"
27 #include "../vehicle.h"
28 #include "../gamemap.h"
29 #include "../graphics/blitter.h"
30 #include "../graphics/drawing.h"
31 #include "../widgets/bargraphwidget.h"
32 #include "../paradialog.h"
33 #include "../gameoptions.h"
34 #include "../events.h"
35 
37 
39 {
40  return marked;
41 };
42 
44 {
45  int old = marked;
46  marked = pos;
47  markChanged(old,pos);
48 };
49 
50 
51 
52 void StoringPosition :: markChanged(int old, int mark)
53 {
54  if ( num == old || num == mark )
55  Redraw();
56 }
57 
58 
59 
60 
61 int StoringPosition :: spWidth = -1;
62 int StoringPosition :: spHeight = -1;
63 
64 PG_Rect StoringPosition :: CalcSize( const PG_Point& pos )
65 {
66  if ( spWidth < 0 ) {
67  Surface& icon = IconRepository::getIcon( "hexfield-bld-1.png" );
68  spWidth = icon.w();
69  spHeight = icon.h();
70  }
71 
72  return PG_Rect( pos.x, pos.y, spWidth, spHeight );
73 }
74 
75 
76 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 )
77  : PG_Widget ( parent, CalcSize(pos), true ), highlight( highLightingManager ), storage( storageVector), num(number), regular(regularPosition), unitPosition( unitPos ), dragState( Off ), dragTarget( NoDragging )
78 {
79  highlight.markChanged.connect( sigc::mem_fun( *this, &StoringPosition::markChanged ));
80  highlight.redrawAll.connect( sigc::bind( sigc::mem_fun( *this, &StoringPosition::Redraw), true));
81 
82  if ( unitPosition.x < 0 ) {
83  unitPosition.x = (Width() - fieldsizex)/2;
84  unitPosition.y = (Height() - fieldsizey)/2;
85  }
86 
87  clippingSurface = Surface::createSurface( spWidth + 10, spHeight + 10, 32, 0 );
88 
89 
90  this->cargoWidget = cargoWidget;
91 }
92 
93 void StoringPosition::setBargraphValue( const ASCString& widgetName, float fraction )
94 {
95  BarGraphWidget* bgw = dynamic_cast<BarGraphWidget*>( FindChild( widgetName, true ) );
96  if ( bgw )
97  bgw->setFraction( fraction );
98 }
99 
100 void StoringPosition::setLabelText ( const ASCString& widgetName, const ASCString& text, PG_Widget* parent )
101 {
102  if ( !parent )
103  parent = this;
104 
105  PG_Label* l = dynamic_cast<PG_Label*>( parent->FindChild( widgetName, true ) );
106  if ( l )
107  l->SetText( text );
108  else {
109  PG_LineEdit* l = dynamic_cast<PG_LineEdit*>( parent->FindChild( widgetName, true ) );
110  if ( l )
111  l->SetText( text );
112  else {
113  PG_MultiLineEdit* l = dynamic_cast<PG_MultiLineEdit*>( parent->FindChild( widgetName, true ) );
114  if ( l )
115  l->SetText( text );
116  }
117  }
118 }
119 
120 
121 void StoringPosition :: eventBlit (SDL_Surface *surface, const PG_Rect &src, const PG_Rect &dst){
122 
123  PG_Draw::BlitSurface( clippingSurface.getBaseSurface(), src, PG_Application::GetScreen(), dst);
124 
125 }
126 
127 
128 void StoringPosition :: eventDraw (SDL_Surface *surface, const PG_Rect &src)
129 {
130  clippingSurface.FillTransparent();
131 
132  ASCString background = "hexfield-bld-";
133  if ( dragTarget == NoDragging ) {
134  background += regular ? "1" : "2";
135  if ( num == highlight.getMark() )
136  background += "h";
137  } else {
138  background += dragTarget==TargetAvail ? "1" : "2";
139  }
140  background += ".png";
141 
142  Surface& icon = IconRepository::getIcon( background );
143 
145  blitter.blit( icon, clippingSurface, SPoint(0,0));
146 
147  if ( num < storage.size() && storage[num] ) {
148  int xpos = unitPosition.x;
149  int ypos = unitPosition.y;
150  if ( num != highlight.getMark() )
151  ypos += 1;
152 
153 
154  storage[num]->direction = 0;
155 
156  if ( storage[num]->getMovement() > 0 )
157  storage[num]->paint( clippingSurface, SPoint(xpos,ypos), 0 ); // storage[num]->getOwner() );
158  else
159  storage[num]->paint( clippingSurface, SPoint(xpos,ypos), true, 0 ); // storage[num]->getMap()->getNeutralPlayerNum() );
160 
161  setBargraphValue( "DamageBar", float(100-storage[num]->damage)/100 );
162 
163  if ( storage[num]->getStorageCapacity().fuel ) {
164  float f = float(storage[num]->getResource( maxint, 2, true, 0 )) / storage[num]->getStorageCapacity().fuel;
165  setBargraphValue( "FuelBar", f );
166  } else
167  setBargraphValue( "FuelBar", 0 );
168 
169  if ( storage[num]->getStorageCapacity().material ) {
170  float f = float(storage[num]->getResource( maxint, 1, true, 0 )) / storage[num]->getStorageCapacity().material;
171  setBargraphValue( "MaterialBar", f );
172  } else
173  setBargraphValue( "MaterialBar", 0 );
174 
175 
176  if ( storage[num]->typ->maxLoadableWeight ) {
177  float f = float(storage[num]->cargoWeight()) / storage[num]->typ->maxLoadableWeight;
178  setBargraphValue( "CargoBar", f );
179  } else
180  setBargraphValue( "CargoBar", 0 );
181 
182  setLabelText( "SlotUnitName", storage[num]->name );
183 
184  ContainerBase* container = storage[num];
185 
186  int slots = 0;
187  for ( ContainerBase::Cargo::const_iterator i = container->getCargo().begin(); i != container->getCargo().end(); ++i )
188  if( *i )
189  ++slots;
190 
191  if ( container->baseType->maxLoadableUnits ) {
192  float f = float( slots ) / float(container->baseType->maxLoadableUnits);
193  setBargraphValue ( "SlotBar", f );
194  } else
195  setBargraphValue ( "SlotBar", 0 );
196 
197 
198  setLabelText( "Weight",ASCString::toString( storage[num]->weight() ));
199 
200 
201  ASCString s;
202  if ( container->baseType->maxLoadableUnits )
203  s.format( "%d / %d", container->cargoWeight(), container->baseType->maxLoadableWeight );
204  else
205  s = "-";
206  setLabelText( "CargoUsage", s );
207 
208  s.format( "%d / %d", slots, container->baseType->maxLoadableUnits );
209  setLabelText( "SlotSummary", s );
210 
211  } else {
212  setBargraphValue( "DamageBar", 0 );
213  setBargraphValue( "FuelBar", 0 );
214  setBargraphValue( "MaterialBar", 0 );
215  setBargraphValue( "CargoBar", 0 );
216  setLabelText( "SlotUnitName", "" );
217  setBargraphValue ( "SlotBar", 0 );
218  setLabelText( "CargoUsage", "" );
219  setLabelText( "SlotSummary", "" );
220  setLabelText( "Weight", "" );
221  }
222 
223  // PG_Draw::BlitSurface( clippingSurface.getBaseSurface(), src, PG_Application::GetScreen(), dst);
224 // PG_Draw::DrawSurface( src, dst);
225 }
226 
227 
228 bool StoringPosition::eventMouseButtonDown(const SDL_MouseButtonEvent* button)
229 {
230  if ( button->type != SDL_MOUSEBUTTONDOWN )
231  return false;
232 
233  if ( button->button == CGameOptions::Instance()->mouse.fieldmarkbutton ) {
234 
235  int oldPos = highlight.getMark();
236  highlight.setNew( num );
237 
238  highlight.clickOnMarkedUnit( num, SPoint(button->x, button->y), num != oldPos );
239  return true;
240  }
241 
242 
243 /*
244  if ( num >= storage.size() || !storage[num] )
245  return false;
246 */
247 
248  int x,y;
249  PG_Application::GetEventSupplier()->GetMouseState(x, y);
250 
251 
252  if ( button->button == CGameOptions::Instance()->mouse.dragndropbutton && cargoWidget && cargoWidget->dragNdropEnabled() && getUnit() ) {
253 
254  SetCapture();
255  dragState = Pressed;
256 
257  dragPointStart.x = x;
258  dragPointStart.y = y;
259 
260  /*
261 
262  dragPointOld.x = x;
263  dragPointOld.y = y;
264 
265 
266  Draging = true;
267  eventDragStart();
268  dragimage = eventQueryDragImage();
269 
270  if(dragimage != NULL) {
271  dragimagecache = PG_Draw::CreateRGBSurface(dragimage->w, dragimage->h);
272  }
273 
274  cacheDragArea(dragPointOld); */
275  return true;
276  }
277 
278  return false;
279 }
280 
281 bool StoringPosition ::eventMouseButtonUp(const SDL_MouseButtonEvent* button)
282 {
283  if ( dragState != Off && (button->button != 4 && button->button != 5 )) {
284  ReleaseCapture();
285  dragState = Off;
286 
287  if ( !cargoWidget )
288  return false;
289 
290  {
291  // EventHandlingMutex ehm;
292 
293  PG_Application::ShowCursor( PG_Application::NONE );
294  PG_Application::SetCursor( NULL );
295  PG_Application::ShowCursor( PG_Application::HARDWARE );
296  }
297 
298  int x,y;
299  PG_Application::GetEventSupplier()->GetMouseState(x, y);
300 
301  // x += mouseCursorOffset.x;
302  // y += mouseCursorOffset.y;
303 
304  StoringPosition* s = dynamic_cast<StoringPosition*>( FindWidgetFromPos (x, y));
305  if ( s )
306  cargoWidget->releaseDrag( s->getUnit() );
307  else {
308  cargoWidget->releaseDrag( x, y);
309  }
310 
311 
312 
313  return true;
314  } else
315  return false;
316 }
317 
318 #define square(x) ((x)*(x))
319 
320 bool StoringPosition::eventMouseMotion (const SDL_MouseMotionEvent *motion)
321 {
322  if ( dragState != Off ) {
323  if ( cargoWidget )
324  cargoWidget->sigDragInProcess();
325 
326  if ( dragState == Pressed ) {
327  if ( square(motion->x - dragPointStart.x) + square(motion->y - dragPointStart.y) > 9 ) {
328  cargoWidget->startDrag( storage[num] );
329  dragState = Dragging;
330 
331  static Surface surf;
332  if ( !surf.valid() ) {
333  surf = Surface::createSurface( fieldsizex+20, fieldsizey+20, 32 ); // somewhat larger because of potential shadow
334  mouseCursorOffset = PG_Point( fieldsizex/2, fieldsizey/2);
335  }
336  surf.Fill( 0 );
337 
339  blitter.blit( IconRepository::getIcon("mouse.png"), surf, SPoint(0,0));
340 
341  // EventHandlingMutex ehm;
342 
343  getUnit()->paint( surf, SPoint(0,0), getUnit()->getOwner() );
344  PG_Application::ShowCursor( PG_Application::NONE );
345  PG_Application::SetCursor( const_cast<SDL_Surface*>( surf.getBaseSurface() ));
346  PG_Application::ShowCursor( PG_Application::SOFTWARE );
347 
348  }
349  }
350  }
351 
352  return false;
353 }
354 
355 
357 {
358  if ( num >= storage.size() || !storage[num] )
359  return NULL;
360  else
361  return storage[num];
362 }
363 
364 
365 vector<StoringPosition*> StoringPosition :: setup( PG_Widget* parent, ContainerBase* container, HighLightingManager& highLightingManager, int& unitColumnCount )
366 {
367  vector<StoringPosition*> storingPositionVector;
368  if ( parent) {
369  int x = 0;
370  int y = 0;
371  int posNum = container->baseType->maxLoadableUnits;
372  if ( container->getCargo().size() > posNum )
373  posNum = container->getCargo().size();
374 
375  for ( int i = 0; i < posNum; ++i ) {
376  StoringPosition* sp = new StoringPosition( parent, PG_Point( x, y), PG_Point(-1,-1), highLightingManager, container->getCargo(), i, container->baseType->maxLoadableUnits >= container->getCargo().size() );
377  storingPositionVector.push_back( sp );
378  x += StoringPosition::spWidth;
379  if ( x + StoringPosition::spWidth >= parent->Width() - 20 ) {
380  if ( !unitColumnCount )
381  unitColumnCount = i + 1;
382  x = 0;
383  y += StoringPosition::spHeight;
384  }
385  }
386  }
387  return storingPositionVector;
388 }
389 
390 
391 
392 
393 CargoWidget :: CargoWidget( PG_Widget* parent, const PG_Rect& pos, ContainerBase* container, bool setup ) : PG_ScrollWidget( parent, pos ), dragNdrop(true), unitColumnCount(0), draggedUnit(NULL)
394 {
395  this->container = container;
396  SetTransparency( 255 );
397 
398  if ( setup )
399  registerStoringPositions( StoringPosition::setup( this, container, unitHighLight, unitColumnCount ), unitColumnCount );
400 
401  if ( my_objVerticalScrollbar )
402  my_objVerticalScrollbar->sigScrollTrack.connect ( sigc::mem_fun( *this, &CargoWidget::handleScrollTrack ));
403 
404  if ( my_objHorizontalScrollbar )
405  my_objHorizontalScrollbar->sigScrollTrack.connect ( sigc::mem_fun( *this, &CargoWidget::handleScrollTrack ));
406 };
407 
408 void CargoWidget::registerStoringPositions( vector<StoringPosition*> sp, const int& colCount )
409 {
410  unitColumnCount = colCount;
411  storingPositionVector = sp;
412  unitHighLight.markChanged.connect( sigc::mem_fun( *this, &CargoWidget::checkStoringPosition ));
413  unitHighLight.clickOnMarkedUnit.connect( sigc::mem_fun( *this, &CargoWidget::click ));
414 }
415 
417 {
418  sigScrollTrack();
419  return true;
420 }
421 
422 
423 
424 void CargoWidget::click( int num, SPoint mousePos, bool first )
425 {
426  if ( container->getCargo().size() > num )
427  unitClicked( container->getCargo()[num], mousePos, first );
428  else
429  unitClicked( NULL, mousePos, first );
430 }
431 
432 
434 {
435  BulkGraphicUpdates bgu( this );
436  unitHighLight.redrawAll();
437 }
438 
439 
440 void CargoWidget :: moveSelection( int delta )
441 {
442  int newpos = unitHighLight.getMark() + delta;
443 
444  if ( newpos < 0 )
445  newpos = 0;
446 
447  if ( newpos >= storingPositionVector.size() )
448  newpos = storingPositionVector.size() -1 ;
449 
450  if ( newpos != unitHighLight.getMark() )
451  unitHighLight.setNew( newpos );
452 }
453 
454 bool CargoWidget :: eventKeyDown(const SDL_KeyboardEvent* key)
455 {
456  if ( key->keysym.sym == SDLK_RIGHT ) {
457  moveSelection(1);
458  return true;
459  }
460  if ( key->keysym.sym == SDLK_LEFT ) {
461  moveSelection(-1);
462  return true;
463  }
464  if ( key->keysym.sym == SDLK_UP ) {
465  moveSelection(-unitColumnCount);
466  return true;
467  }
468  if ( key->keysym.sym == SDLK_DOWN ) {
469  moveSelection(unitColumnCount);
470  return true;
471  }
472  return false;
473 };
474 
475 
476 void CargoWidget :: checkStoringPosition( int oldpos, int newpos )
477 {
478 // PG_Widget* unitScrollAreaw = dynamic_cast<PG_Widget*>(FindChild( "UnitScrollArea", true ));
479 // PG_ScrollWidget* unitScrollArea = dynamic_cast<PG_ScrollWidget*>(FindChild( "UnitScrollArea", true ));
480 // if ( unitScrollArea )
481  if ( newpos < storingPositionVector.size() && newpos >= 0 )
482  ScrollToWidget( storingPositionVector[newpos] );
483 
485 }
486 
488 {
489  int pos = unitHighLight.getMark();
490  if ( !container || pos < 0 || pos >= container->getCargo().size() )
491  return NULL;
492  else
493  return container->getCargo()[pos];
494 }
495 
496 
498 {
499  for ( StoringPositionVector::iterator i = storingPositionVector.begin(); i != storingPositionVector.end(); ++i ) {
500  Vehicle* target = (*i)->getUnit();
501  if ( target && target != v && sigDragAvail( v, target ) ) {
502  (*i)->setDragTarget( StoringPosition::TargetAvail );
503  } else {
504  (*i)->setDragTarget( StoringPosition::TargetNotAvail );
505  }
506  draggedUnit = v;
507  }
508  Redraw();
509 }
510 
512 {
513  for ( StoringPositionVector::iterator i = storingPositionVector.begin(); i != storingPositionVector.end(); ++i )
514  (*i)->setDragTarget( StoringPosition::NoDragging );
515 
516  if ( v )
517  sigDragDone( draggedUnit, v );
518  else
519  sigDragAborted();
520 
521  draggedUnit = NULL;
522 }
523 
524 void CargoWidget :: releaseDrag( int x, int y )
525 {
526  for ( StoringPositionVector::iterator i = storingPositionVector.begin(); i != storingPositionVector.end(); ++i )
527  (*i)->setDragTarget( StoringPosition::NoDragging );
528 
529  if ( IsMouseInside() )
530  sigDragAborted();
531  else
532  sigDragDone( draggedUnit, NULL );
533 
534  draggedUnit = NULL;
535 }
Vehicle * getUnit()
void releaseDrag(Vehicle *v=NULL)
StoringPosition(PG_Widget *parent, const PG_Point &pos, const PG_Point &unitPos, HighLightingManager &highLightingManager, const ContainerBase::Cargo &storageVector, int number, bool regularPosition, CargoWidget *cargoWidget=NULL)
Definition: cargowidget.cpp:76
int maxLoadableUnits
the maximum number of units that can be loaded
sigc::signal< void > sigDragInProcess
Definition: cargowidget.h:127
sigc::signal< bool, Vehicle *, Vehicle * > sigDragAvail
First param: dragged unit, Second Param: target unit.
Definition: cargowidget.h:125
bool dragNdropEnabled() const
Definition: cargowidget.h:133
void blit(const Surface &src, Surface &dst, SPoint dstPos)
Definition: blitter.h:349
bool handleScrollTrack(long data)
sigc::signal< void, Vehicle * > unitMarked
Definition: cargowidget.h:111
int fieldmarkbutton
the button to select a field without opening the menu
Definition: gameoptions.h:130
void setNew(int pos)
Definition: cargowidget.cpp:43
DragTarget dragTarget
Definition: cargowidget.h:79
bool eventMouseButtonUp(const SDL_MouseButtonEvent *button)
static Surface createSurface(int width, int height, SDLmm::Color color=255)
Definition: surface.cpp:387
void FillTransparent()
Definition: surface.cpp:419
ASCString & format(const charT *pFormat,...)
Definition: ascstring.cpp:78
sigc::signal< void, Vehicle *, Vehicle * > sigDragDone
First param: dragged unit, Second Param: target unit.
Definition: cargowidget.h:122
SDL_Surface * getBaseSurface()
Definition: surface.h:116
sigc::signal< void > sigScrollTrack
Definition: cargowidget.h:130
The ASCString class provides an abstract way to manipulate strings.
Definition: ascstring.h:14
#define fieldsizey
Definition: typen.h:441
void redrawAll()
bool eventMouseMotion(const SDL_MouseMotionEvent *motion)
static ASCString toString(int i)
converts the parameter to a String
Definition: ascstring.cpp:193
CargoWidget(PG_Widget *parent, const PG_Rect &pos, ContainerBase *container, bool setup)
static vector< StoringPosition * > setup(PG_Widget *parent, ContainerBase *container, HighLightingManager &highLightingManager, int &unitColumnCount)
sigc::signal< void, int, SPoint, bool > clickOnMarkedUnit
the bool param is set to true if this is the first click on a unit
Definition: cargowidget.h:39
int dragndropbutton
used in the container dialog
Definition: gameoptions.h:149
Vehicle * getMarkedUnit()
void paint(Surface &s, SPoint pos, int shadowDist=-1) const
displays the unit at position spos on s
Definition: vehicle.cpp:1681
bool eventMouseButtonDown(const SDL_MouseButtonEvent *button)
void registerStoringPositions(vector< StoringPosition * > sp, const int &colcount)
sigc::signal< void, int, int > markChanged
Definition: cargowidget.h:35
#define fieldsizex
Definition: typen.h:440
SDLmm::SPoint SPoint
Definition: surface.h:27
static CGameOptions * Instance()
returns the only Instance
Definition: gameoptions.cpp:38
sigc::signal< bool > redrawAll
Definition: cargowidget.h:37
struct CGameOptions::Mouse mouse
void eventBlit(SDL_Surface *surface, const PG_Rect &src, const PG_Rect &dst)
void startDrag(Vehicle *v)
void setFraction(float f)
static Surface & getIcon(const ASCString &name)
int cargoWeight() const
weight of all loaded units
const ContainerBaseType * baseType
the type descriping all non-instance specific properties of the container
Definition: containerbase.h:80
#define maxint
Definition: typen.h:462
#define square(x)
sigc::signal< void, Vehicle *, SPoint, bool > unitClicked
the bool param is set to true if this is the first click on a unit
Definition: cargowidget.h:114
void markChanged(int old, int mark)
Definition: cargowidget.cpp:52
The parent class of Vehicle and Building; The name Container originates from Battle Isle...
Definition: containerbase.h:40
void setLabelText(const ASCString &widgetName, const ASCString &text, PG_Widget *parent=NULL)
vector< Vehicle * > Cargo
void setBargraphValue(const ASCString &widgetName, float fraction)
Definition: cargowidget.cpp:93
bool eventKeyDown(const SDL_KeyboardEvent *key)
const Cargo & getCargo() const
int maxLoadableWeight
the maximum total weight of all loaded units
void eventDraw(SDL_Surface *surface, const PG_Rect &src)
sigc::signal< void > sigDragAborted
Definition: cargowidget.h:128