Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

bmapp.cpp

Go to the documentation of this file.
00001 // $Id$
00002 
00003 //**********************************************************************
00004 //                                                                     *
00005 //    Description:   'Bell Master' TurboVision application class.      *
00006 //                                                                     *
00007 //    Author:        Chris White (whitecf@bcs.org.uk)                  *
00008 //                                                                     *
00009 //    Copyright (C) 2003  Monitor Computing Services Ltd.              *
00010 //                                                                     *
00011 //    This program is free software; you can redistribute it and/or    *
00012 //    modify it under the terms of the GNU General Public License      *
00013 //    as published by the Free Software Foundation; either version 2   *
00014 //    of the License, or any later version.                            *
00015 //                                                                     *
00016 //    This program is distributed in the hope that it will be useful,  *
00017 //    but WITHOUT ANY WARRANTY; without even the implied warranty of   *
00018 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
00019 //    GNU General Public License for more details.                     *
00020 //                                                                     *
00021 //    You should have received a copy of the GNU General Public        *
00022 //    License (http://www.gnu.org/copyleft/gpl.html) along with this   *
00023 //    program; if not, write to:                                       *
00024 //       The Free Software Foundation Inc.,                            *
00025 //       59 Temple Place - Suite 330,                                  *
00026 //       Boston, MA  02111-1307,                                       *
00027 //       USA.                                                          *
00028 //                                                                     *
00029 //**********************************************************************
00030 //                                                                     *
00031 //    Notes:                                                           *
00032 //                                                                     *
00033 //**********************************************************************
00034 
00035 #define Uses_MsgBox
00036 #define Uses_TDeskTop
00037 #define Uses_TEvent
00038 #define Uses_TFileDialog
00039 #define Uses_TKeys
00040 #define Uses_TMenuBar
00041 #define Uses_TMenuItem
00042 #define Uses_TStatusDef
00043 #define Uses_TStatusItem
00044 #define Uses_TStatusLine
00045 #define Uses_TSubMenu
00046 
00047 #include <cstring.h>
00048 #include <fstream.h>
00049 
00050 #include <bcarchst.h>
00051 #include <bclarch.h>
00052 #include <bclist.h>
00053 #include <bellcode.h>
00054 #include <callback.h>
00055 #include <lptnote.h>
00056 #include <mytrace.h>
00057 #include <pcbell.h>
00058 #include <sgarchst.h>
00059 #include <sgmlist.h>
00060 #include <sgnlman.h>
00061 #include <spkrnote.h>
00062 #include <tapper.h>
00063 #include <timeout.h>
00064 #include <tmoutlst.h>
00065 
00066 #include "bmcdwin.h"
00067 #include "bmconst.h"
00068 #include "bmsgwin.h"
00069 #include "bmsplwin.h"
00070 #include "bmsqwin.h"
00071 #include "bmtprwin.h"
00072 
00073 
00074 #include "bmapp.h"
00075 
00076 
00077 
00078 using namespace Monitor::BellMaster;
00079 namespace Ut = Monitor::Utility;
00080 
00081 
00082 
00083 static LptNote        appLpt(1, 7);
00084 static SpeakerNote    appSpeaker(587, 93);
00085 static PcBell         localBell(appLpt);
00086 static PcBell         remoteBell(appSpeaker);
00087 static Tapper         localTapper(remoteBell);
00088 static Tapper         remoteTapper(localBell);
00089 static const char*    applicationVersion = "2.0";
00090 
00091 
00092 
00093 class AppStatusLine : public TStatusLine
00094 {
00095 public:
00096     AppStatusLine(const TRect&    bounds, TStatusDef&    aDefs) :
00097         TStatusLine(bounds, aDefs)
00098         {
00099             _USEMYTRACE_("AppStatusLine::AppStatusLine")
00100         }
00101 
00102     virtual const char* hint(ushort aHelpCtx);
00103 };
00104 
00105 
00106 
00107 const char*
00108 AppStatusLine::hint(ushort aHelpCtx)
00109 {
00110     _USEMYTRACE_("AppStatusLine::hint")
00111 
00112     const char    *commandHint("Guess");
00113 
00114     switch (aHelpCtx)
00115     {
00116     case Const::hcLoadCodes:
00117     {
00118         commandHint = "Load bell codes from a file";
00119         break;
00120     }
00121     case Const::hcQuit:
00122     {
00123         commandHint = "Exit Bellmaster";
00124         break;
00125     }
00126     case Const::hcBeatCode:
00127     {
00128         commandHint = "Beat a bell code";
00129         break;
00130     }
00131     case Const::hcSignalmanRingCode:
00132     {
00133         commandHint = "Get a signalman to beat out a bell code";
00134         break;
00135     }
00136     case Const::hcLoadSignalman:
00137     {
00138         commandHint = "Load a signalman from a description file";
00139         break;
00140     }
00141     case Const::hcUnloadSignalman:
00142     {
00143         commandHint = "Remove a signalman from the simulation";
00144         break;
00145     }
00146     case Const::hcAbout:
00147     {
00148         commandHint = "Display Bell Master build information";
00149         break;
00150     }
00151     default:
00152     {
00153         commandHint = "";
00154         break;
00155     }
00156     }
00157 
00158     return commandHint;
00159 }
00160 
00161 
00162 
00163 App::App() :
00164   TProgInit(&App::initStatusLine,
00165             &App::initMenuBar,
00166             &App::initDeskTop),
00167   bellCodes(new BellCodeList), signalmen(new SignalmanList),
00168   listeningSignalman(0)
00169 {
00170     _USEMYTRACE_("App::App")
00171 
00172 
00173     SplashWin*    splashWindow = new SplashWin(applicationVersion);
00174 
00175     new Ut::Timeout(Ut::DataCallback< App, TView* >(*this,
00176                                                     &App::closeModal,
00177                                                     splashWindow),
00178                     3000,
00179                     "close splash");
00180 
00181     TEvent    initialEvent;
00182 
00183     initialEvent.what            = evCommand;
00184     initialEvent.message.command = Const::cmDisplayModal;
00185     initialEvent.message.infoPtr = splashWindow;
00186 
00187     putEvent(initialEvent);
00188 
00189     loadBellCodesFromFile("default.bcd");
00190     loadSignalmanFromFile("default.sgm");
00191 }
00192 
00193 
00194 
00195 App::~App()
00196 {
00197     _USEMYTRACE_("App::~App")
00198 
00199     delete bellCodes, bellCodes = 0;
00200     delete signalmen, signalmen = 0;
00201 }
00202 
00203 
00204 
00205 TStatusLine*
00206 App::initStatusLine(TRect r)
00207 {
00208     _USEMYTRACE_("App::initStatusLine")
00209 
00210   r.a.y = r.b.y - 1;
00211   return new AppStatusLine(r,
00212                            *new TStatusDef(0,-1) +
00213                            *new TStatusItem(0,
00214                                             kbF10,
00215                                             cmMenu));
00216 }
00217 
00218 
00219 
00220 TMenuBar*
00221 App::initMenuBar(TRect    r)
00222 {
00223     _USEMYTRACE_("App::initMenuBar")
00224 
00225   r.b.y = r.a.y + 1;
00226   return new TMenuBar(
00227     r,
00228     *new TSubMenu("~S~imulation",
00229                   kbAltS) +
00230         *new TMenuItem("E~x~it",
00231                        cmQuit,
00232                        kbAltX,
00233                        Const::hcQuit,
00234                        "Alt-X") +
00235     *new TSubMenu("~C~ode",
00236                   kbAltC) +
00237         *new TMenuItem("~B~eat",
00238                     Const::cmBeatCode,
00239                     kbAltB,
00240                     Const::hcBeatCode,
00241                     "Alt-B") +
00242         newLine() +
00243         *new TMenuItem("~L~oad",
00244                        Const::cmLoadCodes,
00245                        kbAltL,
00246                        Const::hcLoadCodes,
00247                        "Alt-L") +
00248     *new TSubMenu("Si~g~nalman",
00249                   kbAltG) +
00250         *new TMenuItem("~R~ing code",
00251                         Const::cmSignalmanRingCode,
00252                         kbAltR,
00253                         Const::hcSignalmanRingCode,
00254                         "Alt-R") +
00255         newLine() +
00256         *new TMenuItem("l~O~ad",
00257                         Const::cmLoadSignalman,
00258                         kbAltO,
00259                         Const::hcLoadSignalman,
00260                         "Alt-O") +
00261         *new TMenuItem("~U~nload",
00262                        Const::cmUnloadSignalman,
00263                        kbAltU,
00264                        Const::hcUnloadSignalman,
00265                        "Alt-U") +
00266     *new TSubMenu("~H~elp",
00267                   kbAltH) +
00268         *new TMenuItem("~A~bout",
00269                     Const::cmAbout,
00270                     kbAltA,
00271                     Const::hcAbout,
00272                     "Alt-A"));
00273 }
00274 
00275 
00276 
00277 void
00278 App::handleEvent(TEvent&   event)
00279 {
00280     TApplication::handleEvent(event);
00281 
00282     if (event.what == evCommand)
00283     {
00284         switch (event.message.command)
00285         {
00286         case Const::cmLoadCodes:
00287             loadBellCodeFile();
00288             break;
00289         case Const::cmBeatCode:
00290             beatBellCode(localTapper);
00291             break;
00292         case Const::cmSignalmanRingCode:
00293             signalmanRingCode(remoteTapper);
00294             break;
00295         case Const::cmLoadSignalman:
00296             loadSignalmanFile();
00297             break;
00298         case Const::cmUnloadSignalman:
00299             unloadSignalman();
00300             break;
00301         case Const::cmAbout:
00302             event.message.infoPtr = new SplashWin(applicationVersion);
00303         case Const::cmDisplayModal:
00304             showModal((TView*)event.message.infoPtr);
00305             break;
00306         default:
00307             return;
00308         }
00309 
00310         clearEvent(event);
00311     }
00312 }
00313 
00314 
00315 
00316 void
00317 App::idle()
00318 {
00319     TApplication::idle();
00320 
00321     TimeoutList::runTimeouts();
00322 }
00323 
00324 
00325 
00326 void
00327 App::loadBellCodeFile()
00328 {
00329     _USEMYTRACE_("App::loadBellCodeFile")
00330 
00331     TFileDialog*    fileDialog = new TFileDialog("*.bcd",
00332                                                  "Load localBell codes",
00333                                                  "Bell code file",
00334                                                  fdOpenButton,
00335                                                  0);
00336 
00337     if (cmCancel != deskTop->execView(fileDialog))
00338     {
00339         char    fileName[MAXPATH] = { '\0' };
00340 
00341         fileDialog->getFileName(fileName);
00342 
00343         loadBellCodesFromFile(fileName);
00344     }
00345 
00346     destroy(fileDialog);
00347 }
00348 
00349 
00350 
00351 void
00352 App::loadBellCodesFromFile(const char*    fileName)
00353 {
00354     _USEMYTRACE_("App::loadBellCodesFromFile")
00355 
00356     fstream    localBellCodeStream;
00357 
00358     localBellCodeStream.open(fileName, ios::in);
00359 
00360     if (localBellCodeStream.rdbuf()->is_open())
00361     {
00362         BellCodeArchiveStream
00363             localBellCodeArchive(localBellCodeStream);
00364         BellCodeListArchive 
00365             localBellCodeListArchive(localBellCodeArchive);
00366 
00367         localBellCodeListArchive.retrieve(*bellCodes);
00368     }
00369 }
00370 
00371 
00372 
00373 BellCode*
00374 App::selectBellCode(BellCodeList    &availableCodes)
00375 {
00376     _USEMYTRACE_("App::selectBellCode")
00377 
00378     BellCode    *selectedBellCode = 0;
00379 
00380     if (1 > availableCodes.size())
00381     {
00382         messageBox("There are no localBell codes available",
00383                    mfError | mfOKButton);
00384     }
00385     else
00386     {
00387         TRect    bounds = getExtent();
00388         TRect    r(bounds.a.x, bounds.a.y, bounds.b.x, bounds.b.y - 2);
00389 
00390         CodeWindow*    window = new CodeWindow(availableCodes, r);
00391 
00392         if (cmCancel != deskTop->execView(window))
00393         {
00394             selectedBellCode = window->getSelectedBellCode();
00395         }
00396 
00397         destroy(window);
00398     }
00399 
00400     return selectedBellCode;
00401 }
00402 
00403 
00404 
00405 void
00406 App::beatBellCode(Tapper&    tapper)
00407 {
00408     _USEMYTRACE_("App::beatBellCode(tapper)")
00409 
00410 
00411     TapperWin*    tapperWindow = new TapperWin(tapper);
00412 
00413     remoteBell.addListener(
00414         Ut::DataCallback< App, TapperWin* >(*this,
00415                                             &App::signalmanHearBell,
00416                                             tapperWindow));
00417 
00418     deskTop->execView(tapperWindow);
00419 
00420     destroy(tapperWindow);
00421 
00422 
00423     if (0 != listeningSignalman)
00424     {
00425         remoteBell.removeListener(listeningSignalman);
00426 
00427         const string
00428             heardSequence(listeningSignalman->stopListeningToBell());
00429 
00430         TRect    bounds = getExtent();
00431         TRect    r(bounds.a.x, bounds.a.y, bounds.b.x, bounds.b.y - 2);
00432 
00433 
00434         BellCodeList    matchingBellCodes =
00435             bellCodes->matchSequence(heardSequence);
00436 
00437         SequenceWindow*    window =
00438             new SequenceWindow(heardSequence, matchingBellCodes, r);
00439 
00440         if (cmOK == deskTop->execView(window))
00441         {
00442             listeningSignalman->beatSequence(remoteTapper,
00443                                              heardSequence);
00444         }
00445 
00446         destroy(window);
00447 
00448         listeningSignalman = 0;
00449     }
00450 }
00451 
00452 
00453 
00454 void
00455 App::signalmanHearBell(TapperWin*    tapperWindow)
00456 {
00457     _USEMYTRACE_("App::signalmanHearBell(tapperWindow)")
00458 
00459     listeningSignalman = selectSignalman(*signalmen);
00460 
00461     if ((0 != listeningSignalman) && (!listeningSignalman->isBusy()))
00462     {
00463         remoteBell.removeListener(this);
00464 
00465         listeningSignalman->listenToBell(
00466             remoteBell,
00467             Ut::DataCallback< App, TView* >(*this,
00468                                             &App::closeModal,
00469                                             tapperWindow));
00470     }
00471 }
00472 
00473 
00474 
00475 void
00476 App::signalmanRingCode(Tapper&    tapper)
00477 {
00478     _USEMYTRACE_("App::signalmanRingCode(tapper)")
00479 
00480     Signalman    *selectedSignalman = selectSignalman(*signalmen);
00481 
00482     if (0 != selectedSignalman)
00483     {
00484         BellCode    *selectedBellCode = selectBellCode(*bellCodes);
00485 
00486         if (0 != selectedBellCode)
00487         {
00488             selectedSignalman->beatSequence(tapper,
00489                                             selectedBellCode->getSequence());
00490         }
00491     }
00492 }
00493 
00494 
00495 
00496 void
00497 App::loadSignalmanFile()
00498 {
00499     _USEMYTRACE_("App::loadSignalmanFile")
00500 
00501     TFileDialog*    fileDialog = new TFileDialog("*.sgm",
00502                                                  "Load signalman",
00503                                                  "Signalman file",
00504                                                  fdOpenButton,
00505                                                  0);
00506 
00507     if (cmCancel != deskTop->execView(fileDialog))
00508     {
00509         char    fileName[MAXPATH] = { '\0' };
00510 
00511         fileDialog->getFileName(fileName);
00512 
00513         loadSignalmanFromFile(fileName);
00514     }
00515 
00516     destroy(fileDialog);
00517 }
00518 
00519 
00520 
00521 void
00522 App::loadSignalmanFromFile(const char*    fileName)
00523 {
00524     _USEMYTRACE_("App::loadSignalmanFromFile")
00525 
00526     fstream    signalmanStream;
00527 
00528     signalmanStream.open(fileName, ios::in);
00529 
00530     if (signalmanStream.rdbuf()->is_open())
00531     {
00532         SignalmanArchiveStream    signalmanArchive(signalmanStream);
00533 
00534         Signalman    retrievedSignalman;
00535 
00536         signalmanArchive.retrieve(retrievedSignalman);
00537 
00538         signalmen->addSignalman(retrievedSignalman);
00539     }
00540 }
00541 
00542 
00543 
00544 void
00545 App::unloadSignalman()
00546 {
00547     _USEMYTRACE_("App::unloadSignalman")
00548 
00549     Signalman    *selectedSignalman = selectSignalman(*signalmen);
00550 
00551     if (0 != selectedSignalman)
00552     {
00553         signalmen->removeSignalman(*selectedSignalman);
00554     }
00555 }
00556 
00557 
00558 
00559 Signalman*
00560 App::selectSignalman(SignalmanList&    availableSignalmen)
00561 {
00562     _USEMYTRACE_("App::selectSignalman")
00563 
00564     Signalman    *selectedSignalman = 0;
00565 
00566     if (1 > availableSignalmen.size())
00567     {
00568         messageBox("There are no signalmen available", mfError | mfOKButton);
00569     }
00570     else if (1 == availableSignalmen.size())
00571     {
00572         selectedSignalman = &availableSignalmen[0];
00573     }
00574     else
00575     {
00576         TRect    bounds = getExtent();
00577         TRect    r(bounds.a.x, bounds.a.y, bounds.b.x / 2, bounds.b.y / 2);
00578 
00579         SignalmanWindow*    window =
00580             new SignalmanWindow(availableSignalmen, r);
00581 
00582         if (cmCancel != deskTop->execView(window))
00583         {
00584             selectedSignalman = window->getSelectedSignalman();
00585         }
00586 
00587         destroy(window);
00588     }
00589 
00590     return selectedSignalman;
00591 }
00592 
00593 
00594 
00595 void
00596 App::closeModal(TView*    oldView)
00597 {
00598     _USEMYTRACE_("App::closeModal(oldView)")
00599 
00600 
00601     if (deskTop->TopView() == oldView)
00602     {
00603         oldView->endModal(cmCancel);
00604     }
00605 }
00606 
00607 
00608 
00609 void
00610 App::showModal(TView*    newView)
00611 {
00612     _USEMYTRACE_("App::showModal(newView)")
00613 
00614 
00615     deskTop->execView(newView);
00616     destroy(newView);
00617 }

Generated on Wed Oct 29 20:55:43 2003 for Bellmaster BC Turbo Vision by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002