00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <stdio.h>
00026 #include <cstring>
00027 #include <stdlib.h>
00028 #include <SDL_image.h>
00029
00030 #include "guiiconhandler.h"
00031 #include "spfst.h"
00032 #include "iconrepository.h"
00033 #include "mapdisplay.h"
00034 #include "sigc++/retype_return.h"
00035 #include "asc-mainscreen.h"
00036 #include "gameoptions.h"
00037 #include "spfst-legacy.h"
00038
00039 const int guiIconSizeX = 49;
00040 const int guiIconSizeY = 35;
00041 const int guiIconSpace = 5;
00042 const int guiIconColumnNum = 3;
00043
00044
00045 const int smallGuiIconSizeX = 49;
00046 const int smallGuiIconSizeY = 35;
00047 const int smallGuiIconSpace = 2;
00048 const float smallGuiIconSizeFactor = 1;
00049
00050
00051
00052 GuiButton::GuiButton( PG_Widget *parent, const PG_Rect &r ) : PG_Button( parent, r, "", -1, "GuiButton"), func( NULL ), id(-1)
00053 {
00054 sigClick.connect ( SigC::slot( *this, &GuiButton::exec ));
00055 SetBackground( PRESSED, IconRepository::getIcon("empty-pressed.png").getBaseSurface() );
00056 SetBackground( HIGHLITED, IconRepository::getIcon("empty-high.png").getBaseSurface() );
00057 SetBackground( UNPRESSED, IconRepository::getIcon("empty.png").getBaseSurface() );
00058 SetBorderSize(0,0,0);
00059 }
00060
00061 bool GuiButton::exec()
00062 {
00063 if ( func ) {
00064 callFunc( pos, subject, id );
00065 return true;
00066 }
00067 return false;
00068 }
00069
00070
00071 void GuiButton::registerFunc( GuiFunction* f, const MapCoordinate& position, ContainerBase* subject, int id )
00072 {
00073 this->id = id;
00074 this->subject = subject;
00075 func = f;
00076 pos = position;
00077 SetIcon( f->getImage( position, subject, id).getBaseSurface());
00078 }
00079
00080 void GuiButton::unregisterFunc()
00081 {
00082 func = NULL;
00083 id = 0;
00084 subject = NULL;
00085 pos = MapCoordinate(-1,-1);
00086 SetIcon ( (SDL_Surface*) NULL );
00087 }
00088
00089 void GuiButton::eventMouseEnter()
00090 {
00091 PG_Button::eventMouseEnter();
00092 showInfoText();
00093 }
00094
00095 void GuiButton::eventMouseLeave()
00096 {
00097 PG_Button::eventMouseLeave();
00098 MessagingHub::Instance().statusInformation("");
00099 }
00100
00101 void GuiButton::callFunc( const MapCoordinate& pos, ContainerBase* subject, int num )
00102 {
00103 try {
00104 func->execute( pos, subject, id );
00105 } catch ( ActionResult res ) {
00106 errorMessage( res.getMessage() );
00107 }
00108 }
00109
00110
00111 bool GuiButton::checkForKey( const SDL_KeyboardEvent* key, int modifier )
00112 {
00113 if ( func->available( pos, subject, id ))
00114 if ( func->checkForKey( key, modifier, id)) {
00115 callFunc( pos, subject, id );
00116 return true;
00117 }
00118 return false;
00119 }
00120
00121 void GuiButton::showInfoText()
00122 {
00123 if ( func )
00124 MessagingHub::Instance().statusInformation( func->getName(pos, subject, id));
00125 }
00126
00127
00128
00129 SmallGuiButton::SmallGuiButton( PG_Widget *parent, const PG_Rect &r, GuiButton* guiButton, NewGuiHost* host ) : PG_Button( parent, r, "", -1, "GuiButton"), referenceButton( guiButton )
00130 {
00131 sigClick.connect ( SigC::slot( *host, &NewGuiHost::clearSmallIcons ));
00132 sigClick.connect ( SigC::slot( *guiButton, &GuiButton::exec ));
00133
00134 SetBackground( PRESSED, IconRepository::getIcon("empty-pressed.png").getBaseSurface() );
00135 SetBackground( HIGHLITED, IconRepository::getIcon("empty-high.png").getBaseSurface() );
00136 SetBackground( UNPRESSED, IconRepository::getIcon("empty.png").getBaseSurface() );
00137 SetBorderSize(0,0,0);
00138 SetDirtyUpdate(true);
00139
00140 SetBehaviour( SIGNALONRELEASE );
00141
00142 updateIcon();
00143 }
00144
00145
00146 void SmallGuiButton::updateIcon()
00147 {
00148 SDL_Surface* icn = referenceButton->GetIcon( UNPRESSED );
00149 if ( icn ) {
00150 smallIcon = PG_Draw::ScaleSurface( icn, smallGuiIconSizeFactor, smallGuiIconSizeFactor );
00151 SetIcon( smallIcon, NULL, NULL, true );
00152 } else
00153 smallIcon = NULL;
00154 }
00155
00156
00157
00158 void SmallGuiButton::press()
00159 {
00160 SetPressed(true);
00161 Update();
00162 }
00163
00164 void SmallGuiButton::showInfoText()
00165 {
00166 if ( referenceButton && referenceButton->func )
00167 MessagingHub::Instance().statusInformation( referenceButton->func->getName(referenceButton->pos, referenceButton->subject, referenceButton->id));
00168 }
00169
00170
00171 void SmallGuiButton::eventMouseEnter()
00172 {
00173 PG_Button::eventMouseEnter();
00174 showInfoText();
00175 }
00176
00177 void SmallGuiButton::eventMouseLeave()
00178 {
00179 PG_Button::eventMouseLeave();
00180 MessagingHub::Instance().statusInformation("");
00181 }
00182
00183
00184 SmallGuiButton::~SmallGuiButton()
00185 {
00186 }
00187
00188
00189
00190 void GuiIconHandler::eval( const MapCoordinate& pos, ContainerBase* subject )
00191 {
00192 int num = 0;
00193 for ( Functions::iterator i = functions.begin(); i != functions.end(); ++i ) {
00194 if ( (*i)->available(pos, subject, 0 )) {
00195 GuiButton* b = host->getButton(num);
00196 b->registerFunc( *i, pos, subject, 0 );
00197 b->Show();
00198 ++num;
00199 }
00200 }
00201
00202 host->disableButtons(num);
00203 }
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 bool GuiIconHandler::checkForKey( const SDL_KeyboardEvent* key, int modifier )
00223 {
00224 #if 0
00225 if ( !actmap->getCursor().valid())
00226 return false;
00227
00228 ContainerBase* subject = actmap->getField(actmap->getCursor())->getContainer();
00229
00230 for ( Functions::iterator i = functions.begin(); i != functions.end(); ++i )
00231 if ( (*i)->available(actmap->getCursor(), subject, 0 ))
00232 if ( (*i)->checkForKey( key, modifier, 0)) {
00233 (*i)->execute(actmap->getCursor(), subject, 0 );
00234 return true;
00235 }
00236 #endif
00237 return false;
00238 }
00239
00240
00241 void GuiIconHandler::registerUserFunction( GuiFunction* function )
00242 {
00243 functions.push_back ( function );
00244 }
00245
00246
00247 GuiIconHandler::~GuiIconHandler()
00248 {
00249 for ( Functions::iterator i = functions.begin(); i != functions.end(); ++i )
00250 delete *i;
00251
00252 }
00253
00254
00255
00256
00257
00258 NewGuiHost* NewGuiHost::theGuiHost = NULL;
00259
00260 NewGuiHost :: NewGuiHost (MainScreenWidget *parent, MapDisplayPG* mapDisplay, const PG_Rect &r )
00261 : DashboardPanel( parent, r, "GuiIcons", false ) , handler(NULL), enterKeyPressed(false), keyPressedButton(-1)
00262 {
00263 this->mapDisplay = mapDisplay;
00264 mapDisplay->mouseButtonOnField.connect( SigC::slot( *this, &NewGuiHost::mapIconProcessing ));
00265 updateFieldInfo.connect ( SigC::slot( *this, &NewGuiHost::evalCursor ));
00266 theGuiHost = this;
00267
00268 cursorMoved.connect( SigC::hide_return( SigC::slot( *this, &NewGuiHost::clearSmallIcons )) );
00269
00270
00271 PG_Application::GetApp()->sigKeyDown.connect( SigC::slot( *this, &NewGuiHost::eventKeyDown ));
00272 PG_Application::GetApp()->sigKeyUp.connect( SigC::slot( *this, &NewGuiHost::eventKeyUp ));
00273 SetTransparency(255);
00274
00275 parent->lockOptionsChanged.connect( SigC::slot( *this, &NewGuiHost::lockOptionsChanged ));
00276
00277 GameMap::sigMapDeletion.connect( SigC::slot( *this, &NewGuiHost::mapDeleted ));
00278 }
00279
00280 void NewGuiHost::lockOptionsChanged( int options )
00281 {
00282 if ( options & MainScreenWidget::LockOptions::MapActions )
00283
00284 Hide();
00285 else
00286
00287 Show();
00288 }
00289
00290
00291 class SmallButtonHolder : public SpecialInputWidget {
00292 bool locked;
00293 public:
00294 void Lock() { SetCapture(); locked = true; };
00295 void Unlock() { ReleaseCapture(); locked = false; };
00296
00297 SmallButtonHolder (PG_Widget *parent, const PG_Rect &rect ) : SpecialInputWidget( parent, rect ), locked(false) {};
00298 bool eventMouseMotion (const SDL_MouseMotionEvent *motion) { return true; };
00299 bool eventMouseButtonDown (const SDL_MouseButtonEvent *button) { return true; };
00300 bool eventMouseButtonUp (const SDL_MouseButtonEvent *button) { Unlock(); return true; };
00301
00302 bool ProcessEvent(const SDL_Event * event, bool bModal) { return SpecialInputWidget::ProcessEvent( event, bModal ); };
00303 bool ProcessEvent ( const SDL_Event * event )
00304 {
00305
00306
00307
00308
00309
00310
00311
00312
00313 bool result = false;
00314
00315 if ( locked )
00316 ReleaseCapture();
00317
00318 if ( SpecialInputWidget::ProcessEvent( event, true ))
00319 result = true;
00320
00321 if ( locked )
00322 SetCapture();
00323
00324 if ( !result && event->type == SDL_MOUSEBUTTONUP )
00325 Unlock();
00326
00327 return result;
00328 }
00329
00330 };
00331
00332
00333
00334 SmallButtonHolder* NewGuiHost :: smallButtonHolder = NULL;
00335
00336 Command* NewGuiHost :: pendingCommand = NULL;
00337
00338 void NewGuiHost::evalCursor()
00339 {
00340 if ( !actmap )
00341 return;
00342
00343 MapCoordinate mc = actmap->getCursor();
00344
00345 if ( !mc.valid() )
00346 return;
00347
00348 if ( mc.x >= actmap->xsize || mc.y >= actmap->ysize )
00349 return;
00350
00351 ContainerBase* subject = actmap->getField(mc)->getContainer();
00352
00353 eval( mc, subject );
00354 }
00355
00356 void NewGuiHost::mapDeleted( GameMap& map )
00357 {
00358 pendingCommand = NULL;
00359
00360
00361
00362
00363 }
00364
00365
00366 void NewGuiHost::eval( const MapCoordinate& pos, ContainerBase* subject )
00367 {
00368 if ( handler ) {
00369 BulkGraphicUpdates bgu(this);
00370 handler->eval( pos, subject );
00371 }
00372 }
00373
00374
00375 void NewGuiHost::pushIconHandler( GuiIconHandler* iconHandler )
00376 {
00377 if ( !theGuiHost )
00378 return;
00379
00380 if ( theGuiHost->handler )
00381 theGuiHost->iconHandlerStack.push_back( theGuiHost->handler );
00382
00383 theGuiHost->handler = iconHandler;
00384 iconHandler->registerHost( theGuiHost );
00385 updateFieldInfo();
00386 }
00387
00388 GuiIconHandler* NewGuiHost::getIconHandler( )
00389 {
00390 if ( theGuiHost )
00391 return theGuiHost->handler;
00392 else
00393 return NULL;
00394 }
00395
00396
00397 void NewGuiHost::popIconHandler( )
00398 {
00399 if ( !theGuiHost )
00400 return;
00401
00402 theGuiHost->clearSmallIcons();
00403
00404 assert( theGuiHost->handler );
00405
00406 theGuiHost->handler->registerHost( NULL );
00407
00408 theGuiHost->handler = theGuiHost->iconHandlerStack.back();
00409 theGuiHost->iconHandlerStack.pop_back();
00410 updateFieldInfo();
00411 }
00412
00413
00414 GuiButton* NewGuiHost::getButton( int i )
00415 {
00416 while ( i >= buttons.size() ) {
00417 int w = (Width() - 4 * guiIconSpace) / guiIconColumnNum;
00418 GuiButton* b = new GuiButton ( this, PG_Rect( guiIconSpace + i%3 * (w + guiIconSpace), 10 + guiIconSpace + i/3 * (guiIconSpace + guiIconSizeY), guiIconSizeX, guiIconSizeY));
00419 buttons.push_back ( b );
00420 b->Hide();
00421 }
00422 return buttons[i];
00423 }
00424
00425
00426 void NewGuiHost::disableButtons( int i )
00427 {
00428 for ( int j = i; j < buttons.size(); ++j) {
00429 GuiButton* b = getButton(j);
00430 b->Hide();
00431 b->unregisterFunc();
00432 }
00433 }
00434
00435
00436
00437 bool NewGuiHost::mapIconProcessing( const MapCoordinate& pos, const SPoint& mousePos, bool cursorChanged, int button, int prio )
00438 {
00439 if ( prio > 1 )
00440 return false;
00441
00442 if ( button != CGameOptions::Instance()->mouse.fieldmarkbutton )
00443 return false;
00444
00445
00446
00447
00448 SPoint p = mousePos;
00449
00450 MapField* fld = actmap->getField(pos);
00451
00452 bool positionedUnderCursor = false;
00453 if ( ( fld->vehicle || fld->building) && fieldvisiblenow(fld) )
00454 positionedUnderCursor = true;
00455
00456 if ( fld->a.temp ) {
00457 positionedUnderCursor = true;
00458 cursorChanged = false;
00459 }
00460
00461 if ( positionedUnderCursor ) {
00462 p.x -= smallGuiIconSizeX/2;
00463 p.y -= smallGuiIconSizeY/2;
00464 } else {
00465 p.x += 2;
00466 p.y += 2;
00467 }
00468
00469 showSmallIcons( mainScreenWidget, p, cursorChanged );
00470 return true;
00471 }
00472
00473
00474 SmallGuiButton* NewGuiHost::getSmallButton( int i )
00475 {
00476 assert(smallButtonHolder);
00477 while ( i >= smallButtons.size() ) {
00478 PG_Rect r = PG_Rect( (smallGuiIconSizeX + smallGuiIconSpace) * smallButtons.size(), 0, smallGuiIconSizeX, smallGuiIconSizeY );
00479 SmallGuiButton* b = new SmallGuiButton ( smallButtonHolder, r, getButton(i), this);
00480 smallButtons.push_back ( b );
00481 b->Hide();
00482 }
00483
00484 return smallButtons[i];
00485 }
00486
00487
00488 bool NewGuiHost::ProcessEvent (const SDL_Event *event, bool bModal)
00489 {
00490 if ( smallButtonHolder && smallButtonHolder->ProcessEvent( event ))
00491 return true;
00492
00493 if ( DashboardPanel::ProcessEvent( event, bModal ))
00494 return true;
00495
00496 return false;
00497 }
00498
00499
00500
00501 bool NewGuiHost::showSmallIcons( PG_Widget* parent, const SPoint& pos, bool cursorChanged )
00502 {
00503 clearSmallIcons();
00504
00505 BulkGraphicUpdates bgu;
00506
00507 SmallGuiButton* firstSmallButton = NULL;
00508
00509 int count = 0;
00510 if ( !cursorChanged || CGameOptions::Instance()->mouse.singleClickAction ) {
00511 for ( int j = 0; j < buttons.size(); ++j)
00512 if ( !getButton(j)->IsHidden() )
00513 ++count;
00514
00515 if ( count ) {
00516 if ( !smallButtonHolder )
00517 smallButtonHolder = new SmallButtonHolder ( NULL, PG_Rect::null );
00518
00519
00520 smallButtonHolder->MoveWidget( PG_Rect( pos.x, pos.y, count * smallGuiIconSizeX + (count-1)*smallGuiIconSpace, smallGuiIconSizeY ), false );
00521
00522 for ( int j = 0; j < buttons.size(); ++j) {
00523 GuiButton* b = getButton(j);
00524 if ( !b->IsHidden() ) {
00525 SmallGuiButton* sgi = getSmallButton( j );
00526 sgi->updateIcon();
00527 sgi->SetHidden(false);
00528 if ( j == 0 && sgi->IsMouseInside() )
00529 firstSmallButton = sgi;
00530 } else
00531 getSmallButton( j )->SetHidden(true);
00532 }
00533 }
00534 }
00535
00536 bgu.release();
00537 if ( smallButtonHolder && count ) {
00538 smallButtonHolder->BringToFront();
00539 smallButtonHolder->Show();
00540 smallButtonHolder->Lock();
00541
00542 if ( firstSmallButton ) {
00543 firstSmallButton->press();
00544 firstSmallButton->showInfoText();
00545 }
00546 }
00547
00548 return true;
00549 }
00550
00551
00552 bool NewGuiHost::setNewButtonPressed( int i )
00553 {
00554 if ( keyPressedButton == i )
00555 return false;
00556
00557 if ( keyPressedButton >= 0 ) {
00558 GuiButton* button = getButton( keyPressedButton );
00559 if ( button ) {
00560 button->SetPressed(false);
00561 button->SetToggle(false);
00562 }
00563 }
00564
00565 if ( i < buttons.size() || i < 0 ) {
00566 keyPressedButton = i;
00567
00568 if ( keyPressedButton >= 0 ) {
00569 GuiButton* button = getButton( keyPressedButton );
00570 if ( button ) {
00571 button->SetToggle(true);
00572 button->SetPressed(true);
00573 button->showInfoText();
00574 }
00575 }
00576 return true;
00577 }
00578 return false;
00579 }
00580
00581 bool NewGuiHost::eventKeyDown(const SDL_KeyboardEvent* key)
00582 {
00583 int mod = SDL_GetModState() & ~(KMOD_NUM | KMOD_CAPS | KMOD_MODE | SDLK_LSHIFT | SDLK_RSHIFT);
00584 if ( mod )
00585 return false;
00586
00587 if ( !IsVisible() )
00588 return false;
00589
00590 if ( key->keysym.sym == SDLK_RETURN ) {
00591 if ( !enterKeyPressed ) {
00592 mapDisplay->keyboadCursorMovement( false );
00593 enterKeyPressed = true;
00594 setNewButtonPressed( 0 );
00595 }
00596 return true;
00597 }
00598
00599 if ( enterKeyPressed ) {
00600 if ( key->keysym.sym == SDLK_RIGHT || key->keysym.sym == SDLK_KP6 )
00601 return setNewButtonPressed( keyPressedButton + 1);
00602
00603 if ( key->keysym.sym == SDLK_LEFT || key->keysym.sym == SDLK_KP4 )
00604 if ( keyPressedButton > 0 )
00605 return setNewButtonPressed( keyPressedButton - 1);
00606
00607 if ( key->keysym.sym == SDLK_UP || key->keysym.sym == SDLK_KP8 )
00608 if ( keyPressedButton >= guiIconColumnNum )
00609 return setNewButtonPressed( keyPressedButton - guiIconColumnNum );
00610
00611 if ( key->keysym.sym == SDLK_DOWN || key->keysym.sym == SDLK_KP2 )
00612 return setNewButtonPressed( keyPressedButton + guiIconColumnNum );
00613
00614 if ( key->keysym.sym == SDLK_ESCAPE || key->keysym.sym == SDLK_END ) {
00615 enterKeyPressed = false;
00616 mapDisplay->keyboadCursorMovement( true );
00617
00618 setNewButtonPressed( -1 );
00619 return true;
00620 }
00621
00622 } else {
00623 int modifier = SDL_GetModState();
00624 for ( int j = 0; j < buttons.size(); ++j)
00625 if ( getButton(j)->ready() )
00626 if ( getButton(j)->checkForKey( key, modifier ))
00627 return true;
00628
00629 if ( handler )
00630 if ( handler->checkForKey( key, modifier ))
00631 return true;
00632
00633 }
00634
00635 return false;
00636 }
00637
00638 bool NewGuiHost::eventKeyUp(const SDL_KeyboardEvent* key)
00639 {
00640 if ( key->keysym.sym == SDLK_RETURN && enterKeyPressed ) {
00641 enterKeyPressed = false;
00642 mapDisplay->keyboadCursorMovement( true );
00643
00644 GuiButton* button = getButton( keyPressedButton );
00645 if ( button )
00646 button->exec();
00647
00648 setNewButtonPressed( -1 );
00649 return true;
00650 }
00651
00652 return false;
00653 }
00654
00655
00656 #if 0
00657
00658 bool NewGuiHost::clearSmallIcons()
00659 {
00660 bool bulk = PG_Application::GetBulkMode();
00661
00662
00663
00664
00665 bool redraw;
00666 PG_Rect redrawRect;
00667 if ( smallButtonHolder ) {
00668 redraw = true;
00669 redrawRect = *smallButtonHolder;
00670 } else
00671 redraw = false;
00672
00673 delete smallButtonHolder;
00674 smallButtonHolder = NULL;
00675
00676 if ( !bulk ) {
00677
00678
00679 }
00680
00681 return true;
00682 }
00683
00684 #endif
00685
00686 bool NewGuiHost::clearSmallIcons()
00687 {
00688 if ( smallButtonHolder && smallButtonHolder->IsVisible() ) {
00689 smallButtonHolder->Unlock();
00690 smallButtonHolder->Hide();
00691 }
00692 return true;
00693 }
00694
00695
00696 NewGuiHost::~NewGuiHost()
00697 {
00698 if ( handler )
00699 handler->registerHost( NULL );
00700
00701 }
00702
00703 void resetActiveGuiAction( GameMap* map )
00704 {
00705 if ( NewGuiHost::pendingCommand ) {
00706 delete NewGuiHost::pendingCommand;
00707 NewGuiHost::pendingCommand = NULL;
00708 map->cleartemps();
00709 repaintMap();
00710 }
00711 }