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