00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "global.h"
00020
00021 #include <SDL_image.h>
00022 #include <signal.h>
00023
00024 #include <paragui.h>
00025 #include <pgapplication.h>
00026 #include <pgmessagebox.h>
00027 #include <pgdropdown.h>
00028 #include "pgbutton.h"
00029 #include "pglabel.h"
00030 #include "pgwindow.h"
00031 #include "pgscrollbar.h"
00032 #include "pgprogressbar.h"
00033 #include "pgradiobutton.h"
00034 #include "pgthemewidget.h"
00035 #include "pgcheckbutton.h"
00036 #include "pgslider.h"
00037 #include "pglistbox.h"
00038 #include "pgpopupmenu.h"
00039 #include "pgmenubar.h"
00040 #include "pgimage.h"
00041 #include "pgmessagebox.h"
00042 #include "pgwindow.h"
00043 #include "pgrichedit.h"
00044 #include "pgsdleventsupplier.h"
00045 #include "pgmultilineedit.h"
00046 #include "pgtooltiphelp.h"
00047 #include "pglog.h"
00048
00049 #include "widgets/multilistbox.h"
00050 #include "widgets/textrenderer.h"
00051 #include "widgets/autoprogressbar.h"
00052
00053 #include "dialogs/messagedialog.h"
00054
00055 #include "paradialog.h"
00056 #include "events.h"
00057 #include "gameoptions.h"
00058 #include "spfst.h"
00059 #include "strtmesg.h"
00060
00061 #include "graphics/drawing.h"
00062
00063 #include "messaginghub.h"
00064
00065
00066 class EventSupplier: public PG_SDLEventSupplier {
00067 public:
00068
00076 bool PollEvent(SDL_Event* event) {
00077 bool result = getQueuedEvent( *event );
00078 if ( result )
00079 CombineMouseMotionEvents( event );
00080 return result;
00081 };
00082
00090 bool PeepEvent(SDL_Event* event) {
00091 return peekEvent( *event );
00092 }
00093
00100 int WaitEvent(SDL_Event* event)
00101 {
00102 while ( !getQueuedEvent( *event ))
00103 releasetimeslice();
00104 CombineMouseMotionEvents( event );
00105 return 1;
00106 };
00107
00108 } eventSupplier;
00109
00110
00111
00112
00113
00114
00115 ASC_PG_App* pgApp = NULL;
00116
00117
00118 void signalQuit( int i )
00119 {
00120 getPGApplication().Quit();
00121 }
00122
00123
00124 ASC_PG_App :: ASC_PG_App ( const ASCString& themeName ) : fullScreen(false), bitsperpixel(0)
00125 {
00126 this->themeName = themeName;
00127 EnableSymlinks(true);
00128 EnableAppIdleCalls();
00129 sigAppIdle.connect( idleEvent );
00130
00131 int i = 0;
00132 bool themeFound = false;
00133 ASCString path;
00134 do {
00135 path = getSearchPath ( i++ );
00136 if ( !path.empty() ) {
00137 AddArchive ( path );
00138 if ( !themeFound ){
00139 ASCString arch = path + themeName + ".zip";
00140 themeFound = AddArchive ( arch.c_str() );
00141 if ( themeFound )
00142 displayLogMessage( 4, "found dialog theme at " + arch );
00143
00144 }
00145 }
00146 } while ( !path.empty() );
00147 PG_LogConsole::SetLogLevel ( PG_LOG_ERR );
00148
00149 if ( !themeFound )
00150 displayLogMessage( 2, "did not found dialog theme!!" );
00151
00152 reloadTheme();
00153
00154 pgApp = this;
00155 SetEventSupplier ( &eventSupplier );
00156
00157 signal ( SIGINT, &signalQuit );
00158
00159 PG_LineEdit::SetBlinkingTime( 500 );
00160
00161 SetHighlightingTag( '~' );
00162
00163 setMouseUpdateFlag( &CGameOptions::Instance()->hideMouseOnScreenUpdates );
00164
00165 }
00166
00167 bool ASC_PG_App :: queueWidgetForDeletion( PG_Widget* widget )
00168 {
00169 deletionQueue.push_back( widget );
00170 widget->sigDelete.connect( SigC::slot( *this, &ASC_PG_App::removeFromDeletionQueue ));
00171 return true;
00172 }
00173
00174
00175 bool ASC_PG_App :: removeFromDeletionQueue( const PG_MessageObject* obj )
00176 {
00177 DeletionQueue::iterator i = find ( deletionQueue.begin(), deletionQueue.end(), obj );
00178 if ( i != deletionQueue.end() )
00179 deletionQueue.erase( i );
00180 return true;
00181 }
00182
00183
00184 void ASC_PG_App :: setIcon( const ASCString& filename )
00185 {
00186 SDL_Surface *icn = NULL;
00187 try {
00188 tnfilestream iconl ( filename, tnstream::reading );
00189 icn = IMG_Load_RW ( SDL_RWFromStream( &iconl ), 1);
00190
00191 if ( icn )
00192 SDL_WM_SetIcon( icn, NULL );
00193 } catch ( ... ) {}
00194 }
00195
00196 void ASC_PG_App :: Quit()
00197 {
00198 sigQuit(this);
00199 PG_Application::Quit();
00200 }
00201
00202
00203 bool ASC_PG_App::eventQuit(int id, PG_MessageObject* widget, unsigned long data)
00204 {
00205 sigQuit(this);
00206 return PG_Application::eventQuit( id, widget, data );
00207 }
00208
00209 void ASC_PG_App::eventIdle()
00210 {
00211 if ( redrawScreen ) {
00212 PG_Widget::UpdateScreen();
00213 PG_Application::UpdateRect(PG_Application::GetScreen(), 0,0,0,0);
00214 redrawScreen = false;
00215 }
00216
00217 if ( !deletionQueue.empty() )
00218 delete deletionQueue.front();
00219
00220 PG_Application::eventIdle();
00221 }
00222
00223 #include "sdl/graphicsqueue.h"
00224
00225 void ASC_PG_App::SetNewScreenSurface( SDL_Surface* surface )
00226 {
00227 SetScreen(surface, false);
00228 }
00229
00230
00231 bool ASC_PG_App::toggleFullscreen()
00232 {
00233 if ( !GetScreen() )
00234 return false;
00235
00236 int w = GetScreen()->w;
00237 int h = GetScreen()->h;
00238
00239
00240
00241 int flags = SDL_SWSURFACE;
00242 if ( !fullScreen )
00243 flags |= SDL_FULLSCREEN;
00244
00245 queueOperation( new InitScreenOp( w,h,bitsperpixel,flags, InitScreenOp::ScreenRegistrationFunctor( this, &ASC_PG_App::SetNewScreenSurface )), true );
00246 fullScreen = GetScreen()->flags & SDL_FULLSCREEN;
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 PG_Widget::UpdateScreen();
00260
00261
00262
00263 return true;
00264 }
00265
00266
00267 ASC_PG_App& getPGApplication()
00268 {
00269 return *pgApp;
00270 }
00271
00272
00273
00274 StartupScreen::StartupScreen( const ASCString& filename, SigC::Signal0<void>& ticker ) : infoLabel(NULL), versionLabel(NULL), background(NULL), progressBar(NULL), fullscreenImage(NULL)
00275 {
00276 MessagingHub::Instance().statusInformation.connect( SigC::slot( *this, &StartupScreen::disp ));
00277
00278 tnfilestream s ( filename, tnstream::reading );
00279
00280
00281 int rt = 0;
00282 int gt = 0;
00283 int bt = 0;
00284
00285 fullscreenImage = Surface( IMG_Load_RW( SDL_RWFromStream( &s ), true ));
00286 if ( fullscreenImage.valid() ) {
00287 for ( int y = 0; y < fullscreenImage.h(); ++y ) {
00288 for ( int x = 0; x < fullscreenImage.w(); ++x ) {
00289 Uint8 r,g,b;
00290 fullscreenImage.GetPixelFormat().GetRGB( fullscreenImage.GetPixel(x,y), r,g,b );
00291 rt += r;
00292 gt += g;
00293 bt += b;
00294 }
00295 }
00296 rt /= fullscreenImage.h() * fullscreenImage.w();
00297 gt /= fullscreenImage.h() * fullscreenImage.w();
00298 bt /= fullscreenImage.h() * fullscreenImage.w();
00299 }
00300
00301
00302
00303
00304 background = new PG_ThemeWidget(NULL, PG_Rect(0,0,PG_Application::GetScreenWidth(), PG_Application::GetScreenHeight()));
00305 background->SetSimpleBackground(true);
00306 background->SetBackgroundColor( PG_Color( rt, gt, bt ));
00307
00308 if ( fullscreenImage.valid() ) {
00309 float enw = float(PG_Application::GetScreenWidth() )/float(fullscreenImage.w());
00310 float enh = float(PG_Application::GetScreenHeight())/float(fullscreenImage.h());
00311
00312
00313 if ( enw / enh < 0.95 || enw / enh > 1.05 )
00314 enh = enw = min( enw, enh );
00315
00316 int w = int( ceil( enw * fullscreenImage.w()));
00317 int h = int( ceil( enh * fullscreenImage.h()));
00318 PG_Rect rect ( (PG_Application::GetScreenWidth()-w)/2, (PG_Application::GetScreenHeight()-h)/2, w,h);
00319 PG_ThemeWidget* image = new PG_ThemeWidget( background, rect );
00320 image->SetBackground ( fullscreenImage.getBaseSurface(), PG_Draw::STRETCH );
00321 }
00322
00323 int progressHeight = 15;
00324 SDL_Surface* screen = PG_Application::GetApp()->GetScreen();
00325 progressBar = new AutoProgressBar( ticker, background, PG_Rect( 0, screen->h - progressHeight, screen->w, progressHeight ) );
00326
00327 infoLabel = new PG_Label( background, PG_Rect( screen->w/2, screen->h - progressHeight - 25, screen->w/2 - 10, 20 ));
00328 infoLabel->SetAlignment( PG_Label::RIGHT );
00329
00330 if ( MessagingHub::Instance().getVerbosity() > 0 ) {
00331 versionLabel = new PG_Label( background, PG_Rect( 10, screen->h - progressHeight - 25, screen->w/2, 20 ));
00332 versionLabel->SetAlignment( PG_Label::LEFT );
00333 versionLabel->SetText( getVersionString() );
00334 }
00335
00336 background->Show();
00337 }
00338
00339 void StartupScreen::disp( const ASCString& s )
00340 {
00341 infoLabel->SetText( s );
00342 }
00343
00344
00345 StartupScreen::~StartupScreen()
00346 {
00347 progressBar->close();
00348 delete background;
00349 }
00350
00351
00352
00353 bool ASC_PG_App:: InitScreen ( int w, int h, int depth, Uint32 flags )
00354 {
00355 bitsperpixel = depth;
00356 bool result = PG_Application::InitScreen ( w, h, depth, flags );
00357 if ( result ) {
00358 initASCGraphicSubsystem ( GetScreen() );
00359 Surface::SetScreen( GetScreen() );
00360
00361 fullScreen = flags & SDL_FULLSCREEN;
00362
00363 MessagingHub::Instance().error.connect( SigC::bind( SigC::slot( *this, &ASC_PG_App:: messageDialog ), MessagingHubBase::Error ));
00364 MessagingHub::Instance().fatalError.connect( SigC::bind( SigC::slot( *this, &ASC_PG_App:: messageDialog ), MessagingHubBase::FatalError ));
00365 MessagingHub::Instance().warning.connect(SigC::bind( SigC::slot( *this, &ASC_PG_App:: messageDialog ), MessagingHubBase::Warning ));
00366 MessagingHub::Instance().infoMessage.connect( SigC::bind( SigC::slot( *this, &ASC_PG_App:: messageDialog ), MessagingHubBase::InfoMessage ));
00367 }
00368
00369 return result;
00370 }
00371
00372
00373 void ASC_PG_App :: reloadTheme()
00374 {
00375 if ( !LoadTheme(themeName ))
00376 fatalError ( "Could not load Paragui theme for ASC: " + themeName );
00377 }
00378
00379
00380 bool ASC_PG_App :: enableLegacyEventHandling( bool use )
00381 {
00382 return !setEventRouting ( !use, use );
00383 }
00384
00385
00386 void ASC_PG_App::processEvent( )
00387 {
00388 SDL_Event event;
00389 if ( GetEventSupplier()->PollEvent(&event))
00390 PumpIntoEventQueue(&event);
00391 }
00392
00393
00394 int ASC_PG_App::Run ( )
00395 {
00396 enableLegacyEventHandling ( false );
00397 PG_Application::Run();
00398
00399 return 0;
00400 }
00401
00402 ASC_PG_App :: ~ASC_PG_App()
00403 {
00404 while ( !deletionQueue.empty() )
00405 delete deletionQueue.front();
00406
00407 shutdownASCGraphicSubsystem();
00408 }
00409
00410
00411
00412 ASC_PG_Dialog :: ASC_PG_Dialog ( PG_Widget *parent, const PG_Rect &r, const ASCString& windowtext, WindowFlags flags, const ASCString& style, int heightTitlebar )
00413 :PG_Window ( parent, centerRectangle(r), windowtext, flags, style, heightTitlebar ),stdButtonNum(0), caller(0), standardButtonDir( Vertical )
00414 {
00415
00416
00417 int t = GetTransparency();
00418 if ( WindowCounter::num() >= 1 ) {
00419 SetTransparency ( t/2 );
00420 }
00421 }
00422
00423 int WindowCounter::windowNum = 0;
00424
00425
00426 int ASC_PG_Dialog::RunModal()
00427 {
00428 WindowCounter wc;
00429
00430 return PG_Window::RunModal();
00431 }
00432
00433
00434 PG_Rect ASC_PG_Dialog::centerRectangle( const PG_Rect& rect )
00435 {
00436 PG_Rect r = rect;
00437
00438 if ( r.w > PG_Application::GetScreenWidth() )
00439 r.w = PG_Application::GetScreenWidth();
00440
00441 if ( r.h > PG_Application::GetScreenHeight() )
00442 r.h = PG_Application::GetScreenHeight();
00443
00444
00445 if ( r.x < 0 )
00446 r.x = (PG_Application::GetScreenWidth() - r.w) / 2;
00447
00448 if ( r.y < 0 )
00449 r.y = (PG_Application::GetScreenHeight() - r.h) / 2;
00450
00451
00452 if ( r.x + r.w > PG_Application::GetScreenWidth() )
00453 r.x = PG_Application::GetScreenWidth() - r.w;
00454
00455 if ( r.y + r.h > PG_Application::GetScreenHeight() )
00456 r.y = PG_Application::GetScreenHeight() - r.h;
00457
00458 return r;
00459 }
00460
00461 void ASC_PG_Dialog::StandardButtonDirection ( StandardButtonDirectonType dir )
00462 {
00463 standardButtonDir = dir;
00464 }
00465
00466 PG_Button* ASC_PG_Dialog::AddStandardButton( const ASCString& name )
00467 {
00468 ++stdButtonNum;
00469
00470 if ( name.length() == 0 )
00471 return NULL;
00472
00473 if ( standardButtonDir == Vertical )
00474 return new PG_Button( this, PG_Rect( Width() - 110, Height() - stdButtonNum * 40, 100, 30 ), name );
00475 else
00476 return new PG_Button( this, PG_Rect( Width() - 110 * stdButtonNum, Height() -40 , 100, 30 ), name );
00477 }
00478
00479
00480
00481 bool ASC_PG_Dialog::eventKeyDown(const SDL_KeyboardEvent *key){
00482 if(key->keysym.sym == SDLK_ESCAPE) {
00483 closeWindow();
00484 }
00485 return true;
00486 }
00487
00488
00489
00490 bool ASC_PG_Dialog::quitModalLoop(int value )
00491 {
00492 SetModalStatus( value );
00493 PG_Window::QuitModal();
00494 return true;
00495 }
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525 bool ASC_PG_Dialog::closeWindow(){
00526 PG_Window::QuitModal();
00527 if( caller != 0){
00528 caller->SetInputFocus();
00529 }
00530 return true;
00531 }
00532
00533
00534
00535
00536 class AntiBulkHandler {
00537 bool bulk;
00538 public:
00539 AntiBulkHandler() {
00540 bulk = PG_Application::GetBulkMode();
00541 if ( bulk )
00542 PG_Application::SetBulkMode(false);
00543 }
00544 ~AntiBulkHandler() {
00545 if ( bulk )
00546 PG_Application::SetBulkMode(true);
00547 }
00548 };
00549
00550
00551 void ASC_PG_App:: messageDialog( const ASCString& message, MessagingHubBase::MessageType mt )
00552 {
00553 AntiBulkHandler abh;
00554 ASCString title;
00555 ASCString style;
00556 switch ( mt ) {
00557 case MessagingHubBase::Error:
00558 title = "Error";
00559 style = "ErrorMessage";
00560 break;
00561 case MessagingHubBase::Warning:
00562 title = "Warning";
00563 style = "WarningMessage";
00564 break;
00565 case MessagingHubBase::InfoMessage:
00566 title = "Information";
00567 style = "Window";
00568 break;
00569 case MessagingHubBase::FatalError:
00570 title = "Fatal Error";
00571 style = "FatalErrorMessage";
00572 break;
00573 default: break;
00574 };
00575
00576 PG_Rect size = calcMessageBoxSize(message);
00577 MessageDialog msg( NULL, size, title, message,"OK", PG_Label::CENTER, style );
00578 msg.Show();
00579 msg.RunModal();
00580 }
00581
00582
00583 PG_StatusWindowData::PG_StatusWindowData( const ASCString& msg )
00584 {
00585 md = new MessageDialog( NULL, calcMessageBoxSize( msg ), "status", msg, PG_Label::CENTER, "Window" );
00586 md->Show();
00587 };
00588
00589 PG_StatusWindowData::~PG_StatusWindowData()
00590 {
00591 delete md;
00592 };
00593
00594
00595 class NewStringChooser : public ASC_PG_Dialog {
00596 PG_ListBox* listbox;
00597 int button;
00598 int item;
00599
00600 bool buttonpressed( int i )
00601 {
00602 button = i;
00603 QuitModal();
00604 return true;
00605 }
00606
00607 bool itemSelected( PG_ListBoxBaseItem* l )
00608 {
00609 PG_ListBoxDataItem<int>* listitem = dynamic_cast<PG_ListBoxDataItem<int>*>( l );
00610 if ( listitem ) {
00611 item = listitem->getData();
00612 return true;
00613 } else
00614 return false;
00615 }
00616
00617 public :
00618 NewStringChooser ( const ASCString& _title, const vector<ASCString>& _strings , const vector<ASCString>& _buttons, int defaultEntry ) : ASC_PG_Dialog( NULL, PG_Rect( -1, -1, 400, 300 ), _title ), button(-1), item(-1)
00619 {
00620 listbox = new PG_ListBox( this, PG_Rect( 10, 30, Width()-140, Height() - 40) );
00621 listbox->SetMultiSelect( false );
00622 listbox->sigSelectItem.connect( SigC::slot( *this, &NewStringChooser::itemSelected ));
00623
00624 int counter = 0;
00625 for ( vector<ASCString>::const_iterator i = _strings.begin(); i != _strings.end(); ++i ) {
00626 PG_ListBoxDataItem<int>* listitem = new PG_ListBoxDataItem<int>(listbox, 20, *i, counter );
00627 if ( counter == defaultEntry )
00628 listitem->Select();
00629 ++counter;
00630 }
00631
00632 counter = 0;
00633 for ( vector<ASCString>::const_iterator i = _buttons.begin(); i != _buttons.end(); ++i ) {
00634 AddStandardButton(*i)->sigClick.connect( SigC::bind( SigC::slot( *this, & NewStringChooser::buttonpressed ),counter ));
00635 ++counter;
00636 }
00637 }
00638
00639 int getButton()
00640 {
00641 return button;
00642 }
00643 int getItem()
00644 {
00645 return item;
00646 }
00647
00648 };
00649
00650
00651 pair<int,int> new_chooseString ( const ASCString& title, const vector<ASCString>& entries, const vector<ASCString>& buttons, int defaultEntry )
00652 {
00653 NewStringChooser nsc ( title, entries, buttons, defaultEntry );
00654 nsc.Show();
00655 nsc.RunModal();
00656 return make_pair(nsc.getButton(), nsc.getItem() );
00657 }
00658
00659
00660
00661 class MultiLineEditorDialog : public ASC_PG_Dialog {
00662 PG_MultiLineEdit* editor;
00663
00664 public:
00665 MultiLineEditorDialog( const ASCString& title, const ASCString& textToEdit ) : ASC_PG_Dialog( NULL, PG_Rect( -1, -1, 400, 400 ), title), editor(NULL)
00666 {
00667 editor = new PG_MultiLineEdit( this, PG_Rect( 10, 40, Width() - 20, Height() - 80 ) );
00668 editor->SetText( textToEdit );
00669 AddStandardButton( "OK" )->sigClick.connect( SigC::bind( SigC::slot( *this, &MultiLineEditorDialog::quitModalLoop ), 1 ));
00670 }
00671
00672 ASCString GetEditedText() { return editor->GetText(); };
00673 };
00674
00675 bool MultiLineEditor( const ASCString& title, ASCString& textToEdit )
00676 {
00677 MultiLineEditorDialog mle ( title, textToEdit );
00678 mle.Show();
00679 if ( mle.RunModal() ) {
00680 textToEdit = mle.GetEditedText();
00681 return true;
00682 } else
00683 return false;
00684
00685 }
00686
00687 BulkGraphicUpdates :: BulkGraphicUpdates( PG_Widget* parent )
00688 {
00689 bulk = PG_Application::GetBulkMode();
00690 this->parent = parent;
00691 PG_Application::SetBulkMode( true );
00692 active = true;
00693 };
00694
00695
00696 void BulkGraphicUpdates::release()
00697 {
00698 if ( !bulk && active ) {
00699 PG_Application::SetBulkMode( false );
00700 if ( parent )
00701 parent->Update();
00702 }
00703 active = false;
00704 }
00705
00706 BulkGraphicUpdates::~BulkGraphicUpdates()
00707 {
00708 release();
00709 }
00710
00711 void Emboss::eventBlit (SDL_Surface *surface, const PG_Rect &src, const PG_Rect &dst)
00712 {
00713 Surface s = Surface::Wrap( PG_Application::GetScreen() );
00714
00715 PG_Rect clip= dst.IntersectRect( PG_Application::GetScreen()->clip_rect );
00716 if ( inv )
00717 rectangle<4> ( s, SPoint(dst.x, dst.y), dst.w, dst.h, ColorMerger_Brightness<4>( 0.7 ), ColorMerger_Brightness<4>( 1.4 ), clip);
00718 else
00719 rectangle<4> ( s, SPoint(dst.x, dst.y), dst.w, dst.h, ColorMerger_Brightness<4>( 1.4 ), ColorMerger_Brightness<4>( 0.7 ), clip);
00720 };
00721
00722
00723 class StringEditor : public ASC_PG_Dialog {
00724 PG_LineEdit* editor;
00725
00726 public:
00727 StringEditor( const ASCString& title, const ASCString& textToEdit ) : ASC_PG_Dialog( NULL, PG_Rect( -1, -1, 400, 200 ), title), editor(NULL)
00728 {
00729 editor = new PG_LineEdit( this, PG_Rect( 10, 40, Width() - 20, 25 ) );
00730 editor->SetText( textToEdit );
00731 AddStandardButton( "OK" )->sigClick.connect( SigC::bind( SigC::slot( *this, &StringEditor::quitModalLoop ), 1 ));
00732 }
00733
00734 ASCString GetEditedText() { return editor->GetText(); };
00735 };
00736
00737 ASCString editString2( const ASCString& title, const ASCString& defaultValue )
00738 {
00739 StringEditor se ( title, defaultValue );
00740 se.Show();
00741 se.RunModal();
00742 return se.GetEditedText();
00743 }