00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <memory.h>
00016 #include <stdio.h>
00017
00018 #include "CATApp.h"
00019 #include "CATPlatform.h"
00020 #include "CATFileSystem.h"
00021 #include "CATPrefs.h"
00022 #include "CATXMLParser.h"
00023 #include "CATGuiFactory.h"
00024 #include "CATSkin.h"
00025 #include "CATEventDefs.h"
00026
00027 #include "CATWindow.h"
00028 #include "CATControl.h"
00029 #include "CATWaitDlg.h"
00030
00031
00032 CATApp* gApp = 0;
00033
00034
00035
00036
00037
00038
00039
00040 CATApp::CATApp( CATINSTANCE instance,
00041 CATRunMode runMode,
00042 const CATString& appName)
00043 {
00044 try
00045 {
00046 fGUIFactory = 0;
00047 fSkin = 0;
00048 fWaitDlg = 0;
00049
00050 fAppName = appName;
00051 this->fRunMode = runMode;
00052 this->fAppInstance = instance;
00053 gPlatform = new CATPlatform();
00054 fGlobalFileSystem = gPlatform->GetFileSystem();
00055 fExiting = false;
00056
00057
00058 OSOnAppCreate();
00059
00060
00061
00062 CATString skinDirName = L"Skin";
00063 fSkinDir = fGlobalFileSystem->BuildPath(fBaseDir,skinDirName,true);
00064 if (CATFAILED(fGlobalFileSystem->DirExists(fSkinDir)))
00065 {
00066 fGlobalFileSystem->CreateDir(fSkinDir);
00067 }
00068
00069
00070 fHelpDir = fGlobalFileSystem->BuildPath(fBaseDir,"Help",true);
00071
00072
00073 if (runMode != CAT_CONSOLE)
00074 {
00075 if (CATFAILED(fGlobalFileSystem->DirExists(fHelpDir)))
00076 {
00077 fGlobalFileSystem->CreateDir(fHelpDir);
00078 }
00079 }
00080
00081
00082
00083
00084 if (fDataDir.IsEmpty())
00085 {
00086 fDataDir = fGlobalFileSystem->BuildPath(fBaseDir,"Data",true);
00087 }
00088
00089 if (runMode != CAT_CONSOLE)
00090 {
00091 if (CATFAILED(fGlobalFileSystem->DirExists(fDataDir)))
00092 {
00093 fGlobalFileSystem->CreateDir(fDataDir);
00094 }
00095 }
00096
00097
00098
00099
00100 CATString prefsFilename = fGlobalFileSystem->BuildPath(this->GetDataDir(), fAppName);
00101 prefsFilename << ".cfg";
00102 fPrefs = new CATPrefs(prefsFilename);
00103 fTempPrefs = new CATPrefs();
00104
00105 }
00106 catch (...)
00107 {
00108 gApp->DisplayMessage("Error initializing app directories and file system. Exiting");
00109 exit(-1);
00110 }
00111 }
00112
00113
00114
00115 CATApp::~CATApp()
00116 {
00117 if (CATFAILED(fAppLock.Wait()))
00118 {
00119 CATASSERT(false,"Failed to get app lock!");
00120 return;
00121 }
00122
00123 if (fSkin != 0)
00124 {
00125 delete fSkin;
00126 fSkin = 0;
00127 }
00128
00129 if (fWaitDlg != 0)
00130 {
00131 delete fWaitDlg;
00132 fWaitDlg = 0;
00133 }
00134
00135 if (fTempPrefs)
00136 {
00137 delete fTempPrefs;
00138 fTempPrefs = 0;
00139 }
00140
00141
00142 if (fPrefs != 0)
00143 {
00144
00145 CATResult result = CAT_SUCCESS;
00146 if (CATFAILED(result))
00147 {
00148 gApp->DisplayError(result);
00149 }
00150 delete fPrefs;
00151 fPrefs = 0;
00152 }
00153
00154 if (fGlobalFileSystem)
00155 {
00156 gPlatform->Release(fGlobalFileSystem);
00157 CATASSERT(fGlobalFileSystem == 0, "Global based file systems still allocated...");
00158 }
00159
00160 if (fGUIFactory)
00161 {
00162 delete fGUIFactory;
00163 fGUIFactory = 0;
00164 }
00165
00166 FlushResourceCache();
00167
00168 if (gPlatform != 0)
00169 {
00170 delete gPlatform;
00171 gPlatform = 0;
00172 }
00173
00174 fAppLock.Release();
00175 }
00176
00177
00178
00179
00180
00181
00182 CATString CATApp::GetBaseDir()
00183 {
00184 CATResult result = CAT_SUCCESS;
00185
00186 if (CATFAILED(result = fAppLock.Wait()))
00187 {
00188 CATASSERT(false,"Failed to get app lock!");
00189 return "";
00190 }
00191 CATString baseDir = fBaseDir;
00192
00193 fAppLock.Release();
00194
00195 return baseDir;
00196 }
00197
00198
00199
00200
00201
00202
00203 CATString CATApp::GetSkinDir()
00204 {
00205 return fSkinDir;
00206 }
00207
00208 CATString CATApp::GetHelpDir()
00209 {
00210 return fHelpDir;
00211 }
00212
00213
00214
00215
00216
00217
00218 CATString CATApp::GetDataDir()
00219 {
00220 return fDataDir;
00221 }
00222
00223
00224
00225
00226
00227
00228 CATRunMode CATApp::GetRunMode()
00229 {
00230 return fRunMode;
00231 }
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245 CATString CATApp::GetString(CATUInt32 stringId)
00246 {
00247 CATResult result = CAT_SUCCESS;
00248
00249 if (CATFAILED(result = fAppLock.Wait()))
00250 {
00251 CATASSERT(false,"Failed to get app lock!");
00252 return "";
00253 }
00254
00255 CATString theString = this->fStringTable.GetString(stringId);
00256
00257 fAppLock.Release();
00258
00259 return theString;
00260 }
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272 void CATApp::DisplayError(const CATResult& resultCode, CATWindow* wnd)
00273 {
00274 if (resultCode == CAT_SUCCESS)
00275 return;
00276
00277 CATString errorString = gApp->GetString(resultCode);
00278
00279
00280
00281 #ifdef CAT_RESULT_AS_CLASS
00282 CATString additionalInfo = resultCode.GetDescription();
00283 if (additionalInfo.IsEmpty() == false)
00284 {
00285 errorString << kCRLF << additionalInfo;
00286 }
00287 additionalInfo = resultCode.GetFileError();
00288 if (additionalInfo.IsEmpty() == false)
00289 {
00290 errorString << kCRLF << "File: " << additionalInfo;
00291 }
00292
00293 errorString << kCRLF << "Source: " << resultCode.GetFilename() << " ( Line " << resultCode.GetLineNumber() << " )";
00294
00295 #endif
00296
00297 DisplayMessage(errorString,wnd);
00298 }
00299
00300
00301 void CATApp::DisplayMessage(const CATString& message, CATWindow* wnd)
00302 {
00303 (void)this->DisplayPrompt(message, CATPROMPT_OK, wnd);
00304 }
00305
00306 CATResult CATApp::DisplayPrompt( const CATString& message, CATPROMPTTYPE prompt, CATWindow* wnd)
00307 {
00308 CATResult result = CAT_SUCCESS;
00309
00310 if (this->GetRunMode() == CAT_CONSOLE)
00311 {
00312 printf("%s\n",(const char*)message);
00313 if (prompt == CATPROMPT_OK)
00314 {
00315 return CAT_STAT_PROMPT_OK;
00316 }
00317
00318 result = CAT_STAT_IN_PROGRESS;
00319 do
00320 {
00321 char resChar = 0;
00322
00323 switch (prompt)
00324 {
00325 case CATPROMPT_YESNO:
00326 printf("[Y]es or [N]o? ");
00327 resChar = getchar();
00328 if ((resChar | (char) 0x20) == 'y')
00329 {
00330 result = CAT_STAT_PROMPT_YES;
00331 }
00332 else if ((resChar | (char) 0x20) == 'n')
00333 {
00334 result = CAT_STAT_PROMPT_NO;
00335 }
00336 break;
00337
00338 case CATPROMPT_YESNOCANCEL:
00339 printf("[Y]es, [N]o, or [C]ancel? ");
00340 resChar = getchar();
00341 if ((resChar | (char) 0x20) == 'y')
00342 {
00343 result = CAT_STAT_PROMPT_YES;
00344 }
00345 else if ((resChar | (char) 0x20) == 'n')
00346 {
00347 result = CAT_STAT_PROMPT_NO;
00348 }
00349 else if ((resChar | (char) 0x20) == 'c')
00350 {
00351 result = CAT_STAT_PROMPT_CANCEL;
00352 }
00353 break;
00354
00355 case CATPROMPT_OKCANCEL:
00356 printf("[O]kay or [C]ancel? ");
00357 resChar = getchar();
00358 if ((resChar | (char) 0x20) == 'o')
00359 {
00360 result = CAT_STAT_PROMPT_OK;
00361 }
00362 else if ((resChar | (char) 0x20) == 'c')
00363 {
00364 result = CAT_STAT_PROMPT_CANCEL;
00365 }
00366 break;
00367 default:
00368 CATASSERT(false,"Unknown prompt type in console mode!");
00369 break;
00370 }
00371
00372 printf("%s\n", (const char*)this->fStringTable.GetString(result));
00373 } while (result == CAT_STAT_IN_PROGRESS);
00374 }
00375 else
00376 {
00377 DWORD resid = 0;
00378 DWORD promptType;
00379
00380 switch (prompt)
00381 {
00382 case CATPROMPT_YESNO:
00383 promptType = MB_YESNO;
00384 break;
00385 case CATPROMPT_OKCANCEL:
00386 promptType = MB_OKCANCEL;
00387 break;
00388 case CATPROMPT_YESNOCANCEL:
00389 promptType = MB_YESNOCANCEL;
00390 break;
00391 case CATPROMPT_OK:
00392 default:
00393 promptType = MB_OK;
00394 break;
00395 }
00396
00397 HWND parentWnd = 0;
00398 if (wnd)
00399 {
00400 parentWnd = wnd->OSGetWnd();
00401 }
00402 else
00403 {
00404 parentWnd = ::GetActiveWindow();
00405 }
00406
00407 resid = ::MessageBox(parentWnd,message,this->GetAppName(),promptType);
00408
00409 switch (resid)
00410 {
00411 case IDYES:
00412 result = CAT_STAT_PROMPT_YES;
00413 break;
00414 case IDNO:
00415 result = CAT_STAT_PROMPT_NO;
00416 break;
00417 case IDOK:
00418 result = CAT_STAT_PROMPT_OK;
00419 break;
00420 case IDCANCEL:
00421 result = CAT_STAT_PROMPT_CANCEL;
00422 break;
00423 default:
00424 CATASSERT(false,"Unknown prompt type result returned!");
00425 result = CAT_STAT_PROMPT_OK;
00426 }
00427 }
00428 return result;
00429 }
00430
00431
00432 CATResult CATApp::Run()
00433 {
00434 CATResult result = CAT_SUCCESS;
00435
00436 result = OnStart();
00437
00438
00439 if (CATFAILED(result))
00440 {
00441 return result;
00442 }
00443
00444 result = MainLoop();
00445
00446
00447 result = OnEnd(result);
00448
00449 return result;
00450 }
00451
00452
00453 CATResult CATApp::OnStart()
00454 {
00455 return CAT_SUCCESS;
00456 }
00457
00458
00459 CATResult CATApp::OnEnd(const CATResult& result)
00460 {
00461 return result;
00462 }
00463
00464
00465 void CATApp::OnCommand(CATCommand& command, CATControl* ctrl, CATWindow* wnd, CATSkin* skin)
00466 {
00467
00468
00469 CATString cmdString = command.GetCmdString();
00470
00471 CATResult result = CAT_SUCCESS;
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503 if (cmdString.Compare("Help") == 0)
00504 {
00505 this->OnHelp();
00506 }
00507
00508
00509 if (CATFAILED(result))
00510 {
00511 gApp->DisplayError(result);
00512 }
00513 }
00514
00515 CATResult CATApp::OnEvent(const CATEvent& event, CATInt32& retVal)
00516 {
00517 switch (event.fEventCode)
00518 {
00519
00520 case CATEVENT_WINDOW_CLOSE:
00521 {
00522 CATWindow* theWnd = (CATWindow*)event.fVoidParam;
00523
00524 retVal = 1;
00525 return CAT_SUCCESS;
00526 }
00527 break;
00528
00529 case CATEVENT_WINDOW_HIDDEN:
00530
00531 {
00532 CATWindow* theWnd = (CATWindow*)event.fVoidParam;
00533 if (theWnd->IsPrimary())
00534 {
00535 CATResult result = this->GetSkin()->OnEvent(event, retVal);
00536
00537 this->ExitApp();
00538 return result;
00539 }
00540 }
00541 break;
00542
00543
00544 }
00545
00546 return this->GetSkin()->OnEvent(event, retVal);
00547 }
00548
00549 CATResult CATApp::MainLoop()
00550 {
00551 return CAT_SUCCESS;
00552 }
00553
00554
00555
00556
00557 CATString CATApp::GetAppName()
00558 {
00559 return this->fAppName;
00560 }
00561
00562
00563
00564
00565 CATString CATApp::GetAppExePath()
00566 {
00567 this->GetBaseDir();
00568 return this->fProgramPath;
00569 }
00570
00571
00572
00573
00574 CATPrefs* CATApp::GetPrefs()
00575 {
00576 return this->fPrefs;
00577 }
00578
00579
00580
00581
00582 CATPrefs* CATApp::GetTempPrefs()
00583 {
00584 return this->fTempPrefs;
00585 }
00586
00587
00588
00589
00590
00591
00592
00593 CATFileSystem* CATApp::GetGlobalFileSystem()
00594 {
00595 return this->fGlobalFileSystem;
00596 }
00597
00598
00599
00600
00601
00602 CATINSTANCE CATApp::GetInstance()
00603 {
00604 return fAppInstance;
00605 }
00606
00607
00608
00609
00610 CATResult CATApp::LoadSkin(const CATString& skinPath)
00611 {
00612 CATResult result = CAT_SUCCESS;
00613
00614 if (CATFAILED(result = fAppLock.Wait()))
00615 {
00616 return result;
00617 }
00618
00619 if (fSkin != 0)
00620 {
00621 delete fSkin;
00622 fSkin = 0;
00623 }
00624
00625 CATString skinDir, skinFile;
00626 this->fGlobalFileSystem->SplitPath(skinPath, skinDir, skinFile);
00627
00628
00629 if (fGUIFactory == 0)
00630 {
00631 fGUIFactory = new CATGuiFactory(skinDir, skinPath);
00632 }
00633
00634 result = CATXMLParser::Parse( skinPath,
00635 fGUIFactory,
00636 (CATXMLObject*&)fSkin);
00637
00638
00639 if (CATFAILED(result))
00640 {
00641 if (fSkin != 0)
00642 {
00643 delete fSkin;
00644 fSkin = 0;
00645 }
00646 fAppLock.Release();
00647 return result;
00648 }
00649
00650
00651 result = fSkin->Load(SkinLoadCB, this, 0.0, 1.0f);
00652 if (CATFAILED(result))
00653 {
00654 delete fSkin;
00655 fSkin = 0;
00656 }
00657
00658 fAppLock.Release();
00659
00660 return result;
00661 }
00662
00663 void CATApp::SkinLoadCB( CATFloat32 progress, const CATString& status, void* userParam)
00664 {
00665 CATApp* app = (CATApp*)userParam;
00666 CATString statString = "Loading Skin: ";
00667 statString << status;
00668 app->SetWaitStatus( statString, progress);
00669 }
00670
00671
00672
00673
00674 CATSkin* CATApp::GetSkin()
00675 {
00676 return fSkin;
00677 }
00678
00679
00680 void CATApp::ExitApp()
00681 {
00682 fExiting = true;
00683
00684
00685
00686 CATPostQuit(0);
00687 }
00688
00689 bool CATApp::IsExiting()
00690 {
00691 return fExiting;
00692 }
00693
00694 void CATApp::OnHelp()
00695 {
00696 this->DisplayError(CATRESULT(CAT_ERR_NO_HELP_AVAILABLE));
00697 }
00698
00699
00700
00701 CATResult CATApp::AddResourceImage( const CATString& path, CATImage* image)
00702 {
00703 CATImage* oldImage = 0;
00704 std::map<CATString, CATImage*>::iterator iter = fImageCache.find(path);
00705 if (iter != fImageCache.end())
00706 {
00707 return CATRESULT(CAT_STAT_IMAGE_ALREADY_LOADED);
00708 }
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719 image->AddRef();
00720 fImageCache.insert(std::make_pair(path,image));
00721 return CAT_SUCCESS;
00722 }
00723
00724
00725 CATResult CATApp::GetResourceImage( const CATString& path, CATImage*& image)
00726 {
00727 std::map<CATString, CATImage*>::iterator iter = fImageCache.find(path);
00728 if (iter != fImageCache.end())
00729 {
00730 image = iter->second;
00731 image->AddRef();
00732 return CAT_SUCCESS;
00733 }
00734
00735 return CATRESULT(CAT_ERR_IMAGE_NULL);
00736 }
00737
00738
00739
00740 CATResult CATApp::FlushResourceCache()
00741 {
00742 std::map<CATString, CATImage*>::iterator iter = fImageCache.begin();
00743 while (iter != fImageCache.end())
00744 {
00745 if (iter->second->GetRefCount() == 1)
00746 {
00747 CATImage::ReleaseImage(iter->second);
00748 iter = fImageCache.erase(iter);
00749 }
00750 else
00751 {
00752 ++iter;
00753 }
00754 }
00755
00756 return CAT_SUCCESS;
00757 }
00758
00759
00760 CATResult CATApp::InitWaitDlg(CATInt32 bmpId, CATRect& textRect, CATInt32 progOnId, CATInt32 progOffId, CATInt32 progLeft, CATInt32 progTop)
00761 {
00762 if (fWaitDlg != 0)
00763 delete fWaitDlg;
00764
00765 fWaitDlg = new CATWaitDlg(this->fAppInstance, bmpId, textRect, progOnId, progOffId, progLeft, progTop);
00766
00767 if (fWaitDlg != 0)
00768 return CAT_SUCCESS;
00769
00770 return CATRESULT(CAT_ERR_OUT_OF_MEMORY);
00771 }
00772
00773 CATWaitDlg* CATApp::GetWaitDlg()
00774 {
00775 CATASSERT(fWaitDlg != 0, "Calling GetWaitDlg() prior to initializing it with InitWaitDlg()!");
00776 return fWaitDlg;
00777 }
00778
00779
00780 void CATApp::SetWaitString(const CATString& waitStr)
00781 {
00782 if (fWaitDlg != 0)
00783 fWaitDlg->SetWaitLabelText(waitStr);
00784 }
00785
00786 void CATApp::SetWaitProgress(CATFloat32 progress)
00787 {
00788 if (fWaitDlg != 0)
00789 fWaitDlg->SetProgress(progress);
00790 }
00791
00792 void CATApp::SetWaitStatus( const CATString& waitStr, CATFloat32 progress)
00793 {
00794 if (fWaitDlg)
00795 {
00796 fWaitDlg->SetWaitLabelText(waitStr);
00797 fWaitDlg->SetProgress(progress);
00798 }
00799 }
00800
00801 CATString CATApp::GetVersionString()
00802 {
00803 CATString versionString;
00804 versionString = this->GetAppName();
00805 versionString << (CATWChar)0x2122;
00806
00807
00808
00809 CATString ourFile = this->GetAppExePath();
00810
00811 DWORD dummyZero = 0;
00812 CATUInt32 infoSize = ::GetFileVersionInfoSize(ourFile,&dummyZero);
00813
00814 if (infoSize > 0)
00815 {
00816 CATUInt8* dataBuffer = new CATUInt8[infoSize*sizeof(CATWChar)];
00817 if (::GetFileVersionInfo(ourFile,dummyZero,infoSize,dataBuffer))
00818 {
00819 VS_FIXEDFILEINFO* prodVerPtr = 0;
00820 unsigned int prodVerLen = 0;
00821
00822 if (::VerQueryValue(dataBuffer,L"\\",(void**)&prodVerPtr,&prodVerLen))
00823 {
00824 CATUInt8 majorVersion = (CATUInt8)((prodVerPtr->dwProductVersionMS & 0xFF0000) >> 16);
00825 CATUInt8 minorVersion = (CATUInt8)((prodVerPtr->dwProductVersionLS & 0xFF0000) >> 16);
00826 CATUInt8 subVersion = (CATUInt8)((prodVerPtr->dwProductVersionLS & 0xFF));
00827 versionString << L" Version: " << (char)(majorVersion + '0') << L"."
00828 << (char)(minorVersion + '0') << (char)(subVersion + '0');
00829 }
00830 }
00831
00832 delete [] dataBuffer;
00833 }
00834
00835 return versionString;
00836 }
00837
00838