/* naytto.cpp */ /****************************************************************************/ /* ** N A Y T T O . C P P ** ** Näyttö-luokan toteutus ** ** Tekijät: Vesa Lappalainen ** Ohjelmointikurssi 1991 ** Tehty: 20.12.1991 ** Muutettu: 10.12.1995 ** Mitä muutettu: Muutettu C++ luokaksi ** Muutettu: 28.12.1995/vl ** Mitä muutettu: Laitettu uuden jäsenen lukeminen toimivaksi ** Muutettu: 02.01.1996/vl ** Mitä muutettu: Lisätty oikeellisuustarkistus ja valmius ** lista-tyyppisiin kenttiin ** ks. kysy_tavallinen_kentta ja kysy_listakentta ** Lisätty helpin käyttö ** Muutettu: 07.01.1996/vl ** Mitä muutettu: Lisätty mahdollisuus kääntää määrittelemällä ** vakio USE_CONSOLE ja lisäämällä tällöin editlue.c:n ** vaatimat muut tiedosto projektiin. Näin voidaan ** saada näyttöeditointi mukaan silloin kuin ** console.c on kohdelaitteistolle sovitettu ** (7.1.1996: BorlandC, HP-UX, Linux, AIX, ks. console.c) ** Muutettu: 20.01.1997/vl ** Mitä muutettu: Jäsenet erilleen kerhosta ** lue_tiedosto ja cNaytto(...) parametrilistaa muutettu ** jotta voidaan lukea esim. komento rivillä annettu tied. ** ** ** Tietorakenne on seuraava: ** ** ** cNaytto cKerho ** ------ ** | o-----> |---| ** | | | | ** | | | | ** | | | | ** | | |---| ** ------ ** ** Käytössä voi olla monta näyttöä, joista jokainen voi osoittaa samaan ** tai eri kerhoon. Näyttö huolehtii kaikesta käyttöliittymään ** liittyvästä. Näyttö ei tiedä kerhon rakenteesta muuta kuin, että ** kerhon voi lukea levyltä ja kirjoittaa levylle sekä siihen voi ** lisätä ja etsiä jäseniä. Näyttö tietää että on olemassa jäsen, ** muttei se tiedä jäsenen yksityiskohtia. ** ** Näyttöluokka voidaan kirjoittaa uusiksi esimerkiksi Windows- ** toteuteusta varten. Tämä näyttöluokka on ANSI C++:n mukainen, ** standardi-päätettä käyttävä versio. ** ** Public-metodeja: ** ================ ** cNaytto(cKerho *p) ** - alustetaan naytto kayttaen naytossa kerhoa johon p osoittaa ** ** ~cNaytto() ** - hävitetään näyttö. Talletetaan jollei ole vielä tehty ** ** void ohjeet(void); ** - lyhyt tiedotus ohjelmasta ** ** void kiitokset(void); ** - poistumiskiitokset ** ** int lue_tiedostosta(); ** - luetaan kerhon nimi ja sitten luetaan kerho tiedostosta ** Luodaan uusi, jollei kerhoa löydy levyltä. ** ** int talleta(); ** - talletaan kerho levylle (jos siinä on muutoksia). ** vanha kerho jää .bak -nimelle ** ** int paavalinta(); ** - tulostetaan päämenu ja odotetaan valintaa sekä suoritetaan ** valittu toimenpide. Toistetaan silmukassa kunnes valitaan ** poistuminen. ** Toistaiseksi vasta lisääminen toimii Aku Ankalla ja ** tulostus alkeellisesti näyttöön ** ** */ #include #include using namespace std; #include "naytto.h" #include "ioali.h" #include "mjonotpp.h" #include "editlue.h" // Tämä vaikuttaa vain jos on vakio USE_CONSOLE #include "wout.h" #include "help.h" #include "kentta.h" //============================================================================ // Vakiota //============================================================================ #define VERSIO "2002.01.12" static const int OLET_ALKU = 19; static const int VAKANEN = 33; static const char *TARKENNIN = ".dat"; static const char *VANHATARK = ".bak"; //============================================================================ // Merkkijonot, jotka tarkoittavat jotakin toimintoa ja niiden käsittely //============================================================================ typedef struct { eToiminto komento; const char *jono; } tKomento; static tKomento komennot[] = { { TOIM_LOPETA , "q" }, { TOIM_EDELLINEN , "^" }, { TOIM_LOPUT_OLETUS, ",|." }, { TOIM_JATKA , NULL } }; static eToiminto mika_komento(const string &s) { for (int i=0; komennot[i].jono; i++) if ( joku_jono(s,komennot[i].jono,"|") == 0 ) return komennot[i].komento; return TOIM_JATKA; } //============================================================================ // Näytön yleinen käsittely: //============================================================================ void cNaytto::logo(void) { cout << endl; cout << " ###################################" << endl; cout << " # J Ä S E N R E K I S T E R I #" << endl; cout << " # versio 9.95 #" << endl; cout << " # Hannu Hanhi #" << endl; cout << " ###################################" << endl; } void cNaytto::ohjeet(void) { logo(); cout << endl; cout << "Tällä ohjelmalla ylläpidetään kerhon jäsenrekisteriä." << endl; } void cNaytto::kiitokset(void) { cout << endl; cout << "KIITOS KÄYTÖSTÄ JA TERVETULOA UUDELLEEN" << endl; cout << endl << endl << endl; } //============================================================================ // Näytön kerhon tunteva osuus: //============================================================================ //---------------------------------------------------------------------------- int cNaytto::lue_tiedosto(const string &tied_nimi) /* ** Luetaan kerho levyltä. ** Ensin kysytään kerhon nimi. Jos kerhoa ei ole, utellaan ** lisätietoja ja luodaan se. ----------------------------------------------------------------------------*/ { string tied,nimi; int maksimi; if ( tied_nimi != "" ) { tied = tied_nimi; goto jatka; } if ( kerho->Tiedoston_nimi() != "" ) { tied = kerho->Tiedoston_nimi(); goto jatka; } // Poista goto?? do { // Kysellään kunnes tiedosto aukeaa tai luodaan uusi cout << endl; cout << "Anna kerhon nimi>"; lue_rivi(cin,tied); if ( tied == "" ) return ilmoitus("Tiedoston nimeä ei annettu"); jatka: laita_tarkennin(tied,TARKENNIN); if ( onko_tiedostoa(tied) ) return ilmoitus(kerho->lue_tiedostosta(tied)); cout << "Tiedostoa " << tied << " ei ole!" << endl; } while ( kylla_kysymys("Luodaanko uusi tiedosto?") == 0 ); cout << endl; cout << "Anna kerhon koko nimi >"; lue_rivi(cin,nimi); cout << "Anna kerhon maksimi koko >"; lue_rivi(cin,maksimi); return ilmoitus(kerho->luo(tied,nimi,maksimi)); } //---------------------------------------------------------------------------- int cNaytto::talleta() /* ** Jos kerhossa muutoksia, niin ** Nimetään vanha tiedosto .bak -nimelle ja talletetaan ** nykyinen tiedosto vanhan tilalle. ----------------------------------------------------------------------------*/ { logo(); if ( !kerho->Muutettu() ) return 0; int vanhat_pilalla = kerho->TeeBak(VANHATARK); if ( ilmoitus(kerho->talleta()) ) return 1; cout << endl; cout << "Tiedot talletettu tiedostoon " << kerho->Tiedoston_nimi() << endl; if ( !vanhat_pilalla ) cout << "Vanhat tiedot tiedostossa " << kerho->Bak_nimi() << endl; return 0; } //---------------------------------------------------------------------------- int cNaytto::kysy_talleta() { if ( !kerho->Muutettu() ) return 0; if ( kylla_kysymys("Talletetaanko tiedot") ) return talleta(); return 0; } //---------------------------------------------------------------------------- void cNaytto::tulosta(std::ostream &os,const cJasen &jasen) { jasen.tulosta(os); } /****************************************************************************/ static eToiminto /* */ kysy_kentta( /* */ const string &viesti ,/* s Viesti joka tulee näytölle */ string &jono /* t Jono johon kentän vastaus luetaan. */ ) /* ** Funktiolla luetaan vastaus kenttään. ** ** Globaalit: POIS (jono, jolla syöttö katkaistaan) ** Syöttö: päätteeltä ** Tulostus: näyttöön ** Kutsuu: lue_jono_oletus ----------------------------------------------------------------------------*/ { string apu(jono); int paluu; eToiminto toim; paluu = lue_jono_oletus(viesti,OLET_ALKU,VAKANEN,apu); if ( paluu < OLETUS ) return TOIM_LOPETA; if ( ( toim = mika_komento(apu) ) != TOIM_JATKA ) return toim; poista_tyhjat(apu); jono = apu; return TOIM_JATKA; } //---------------------------------------------------------------------------- eToiminto cNaytto::kysy_tavallinen_kentta(cJasen &jasen, int k) /* ** Kysytään tavallisen kentän tiedot. Palautetaan tieto miten pitää ** jatkaa: ** TOIM_LOPETA - ei kysellä enää, eikä jäsenen tietoja saa käyttää ** TOIM_SEURAAVA - voi kysyä seuraav kentän tiedot ** TOIM_EDELLINEN - täytyy kysyä edellisen kentän tiedot ** TOIM_KYSY_UUDELLEEN - tiedot täytyy kysyä uudelleen ** ** 1. kysymyksestä pääsee pois pelkällä RETURNin painamisella. ** Jos yritetään lisätä sellaisia kenttiä,, joista täytyy olla ** yksikäsitteinen arvo, joko varoitetaan tai kieltäydytään lisäämisestä. ** Kentän sijoittaminen osaa ilmoittaa tämän. ** ** Toteuteuksessa on vielä se vika, että jos palataan edelliseen jo ** kerran varmistettuun kenttään, niin taas kentästä poistuttaessa ** varmistus kysytään uudelleen. Vika saataisiin pois määrittelemällä ** taulukko, johon merkitään mitkä kentät on jo hyväksytty. Hyväksyntä ** pitää tietysti aina poistaa jos kentän sisältö muuttuu! ----------------------------------------------------------------------------*/ { int lkm,kuka; cKenttavirhe virhe; eToiminto toiminto; string edell; // Apumuuttuja johon jemmataan kentän vanha arvo string jono; edell = jono = jasen.kentta_jonoksi(k); edit_vaihda_muunnos(jasen.kentta_muunnos(k)); // Jos näyttöeditointi toiminto = kysy_kentta(jasen.kysymys(k),jono); if ( toiminto != TOIM_JATKA ) return toiminto; if ( k == jasen.eka_kysymys() && jono == "" ) return TOIM_LOPETA; // 1. kys. pois pelk. ret if ( jono == HELP_JONO ) { help.aihe(jasen.help_aihe(k)); return TOIM_KYSY_UUDELLEEN; } virhe = jasen.sijoita(k,jono); switch ( virhe.Taso() ) { case KENTTA_OK: return TOIM_SEURAAVA; case KENTTA_VAROITUS: cout << virhe.Virhe() << endl; return TOIM_SEURAAVA; case KENTTA_UUDELLEEN: case KENTTA_MUUTETTU_KYSY: cout << virhe.Virhe() << endl; return TOIM_KYSY_UUDELLEEN; case KENTTA_OK_ONKO_AINOA: lkm = kerho->laske_montako_muuta(jasen,k,kuka); if ( lkm == 0 ) return TOIM_SEURAAVA; kerho->anna_jasen(kuka).tulosta(cout); cout << "On jo ennestään!" << endl; jasen.sijoita(k,edell); return TOIM_KYSY_UUDELLEEN; case KENTTA_OK_VAROITA_MUUT: lkm = kerho->laske_montako_muuta(jasen,k,kuka); if ( lkm == 0 ) return TOIM_SEURAAVA; kerho->anna_jasen(kuka).tulosta(cout); if ( kylla_kysymys("On jo, lisätäänkö silti uusi!") ) return TOIM_SEURAAVA; jasen.sijoita(k,edell); return TOIM_KYSY_UUDELLEEN; default: ; } // virhe.Taso() return TOIM_SEURAAVA; } //---------------------------------------------------------------------------- int cNaytto::kysy_tiedot(cJasen &jasen) { cJasen apujasen(jasen); int k,eka=apujasen.eka_kysymys(),kenttia = apujasen.kenttia(); eToiminto toiminto; k = eka; do { if ( k < eka ) k = eka; switch ( apujasen.kentan_tyyppi(k) ) { case KENTTA_NORMAALI: toiminto = kysy_tavallinen_kentta(apujasen,k); break; case KENTTA_LISTA: toiminto = kysy_listakentta(apujasen,k); break; default: return 1; } switch ( toiminto ) { case TOIM_SEURAAVA: k++; break; case TOIM_EDELLINEN: k--; break; case TOIM_KYSY_UUDELLEEN: break; case TOIM_LOPUT_OLETUS: k = kenttia; break; case TOIM_LOPETA: return 1; default: ; } } while ( k < kenttia ); jasen = apujasen; return 0; } //---------------------------------------------------------------------------- eToiminto cNaytto::kysy_listakentta(cJasen &, int ) /* ** Kysytään listatyyppisen kentän tiedot. ** Ei toteutettu! ----------------------------------------------------------------------------*/ { return TOIM_SEURAAVA; } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- void cNaytto::lisaa_uusi_jasen(char valinta) /* ** Kysellään uusien jäsenien tietoja ja lisätään jäsenet. ----------------------------------------------------------------------------*/ { cJasen jasen(kerho->anna_jasen(nykyjasen)); // Kerho hoitaa jos -1 otsikko(valinta,"Uuden jäsenen lisäys"); while ( 1 ) { jasen.tyhjenna_omat(); jasen.rekisteroi(); cout << endl; cout << "Jäseniä on nyt " << kerho->Jasenia() << "." << endl; cout << "Anna uusi nimi muodossa sukunimi etunimi" << endl; do { if ( kysy_tiedot(jasen) != 0 ) return; cout << "Lisätäänkö" << endl; jasen.tulosta(cout); } while ( kylla_kysymys("") == 0 ); if ( ilmoitus(kerho->lisaa(jasen)) ) return; nykyjasen = kerho->Jasenia()-1; } } //---------------------------------------------------------------------------- void cNaytto::etsi_jasenen_tiedot(char valinta) { otsikko(valinta,"Etsi jäsenen tiedot"); ei_toimi(); } //---------------------------------------------------------------------------- void cNaytto::tulosteet(char valinta) /* ** Tulostetaan kaikki jäsenet näytölle. ----------------------------------------------------------------------------*/ { otsikko(valinta,"Tulosteet"); cout << "Toimii toistaiseksi vain näytölle" << endl; viivarivi(78,'-'); for (int i=0; iJasenia(); i++) { const cJasen &jasen = kerho->anna_jasen(i); tulosta(cout,jasen); cout << endl; } viivarivi(78,'-'); odota_jotakin(); } //---------------------------------------------------------------------------- void cNaytto::tietojen_korjailu(char valinta) { otsikko(valinta,"Tietojen korjailu"); ei_toimi(); } //---------------------------------------------------------------------------- void cNaytto::paivita_jasenmaksuja(char valinta) { otsikko(valinta,"Päivitä jäsenmaksuja"); ei_toimi(); } //---------------------------------------------------------------------------- void cNaytto::avustus(char valinta) { otsikko(valinta,"Avustus"); help.hakemisto(); } //---------------------------------------------------------------------------- void cNaytto::paamenu() { cout << endl << endl << endl << endl << endl << endl; cout << "Jäsenrekisteri" << endl; cout << "==============" << endl; cout << "" << endl; cout << "Kerhossa " << kerho->Kerhon_nimi() << " on " << kerho->Jasenia() << " jäsentä." << endl; cout << "" << endl; cout << "Valitse:" << endl; cout << " ? = avustus" << endl; cout << " 0 = lopetus" << endl; cout << " 1 = lisää uusi jäsen" << endl; cout << " 2 = etsi jäsenen tiedot" << endl; cout << " 3 = tulosteet" << endl; cout << " 4 = tietojen korjailu" << endl; cout << " 5 = päivitä jäsenmaksuja" << endl; cout << " :"; } //---------------------------------------------------------------------------- int cNaytto::paavalinta() { char nappain; while (1) { paamenu(); nappain = odota_nappain("?012345",EI_OLETUSTA,MERKKI_ISOKSI); switch (nappain) { case '?': avustus(nappain); break; case '0': return 0; case '1': lisaa_uusi_jasen(nappain); break; case '2': etsi_jasenen_tiedot(nappain); break; case '3': tulosteet(nappain); break; case '4': tietojen_korjailu(nappain); break; case '5': paivita_jasenmaksuja(nappain); break; default : cout << "Näin ei voi käydä!" << endl; return 1; } } } //---------------------------------------------------------------------------- void cNaytto::alusta(cKerho *p,const string &ohj_nimi) { nykyjasen = -1; kerho = p; if ( ohj_nimi == "") ohjelman_nimi = "kerho"; else ohjelman_nimi=ohj_nimi; help.alusta(ohjelman_nimi); edit_alusta("kerho.lyh"); } //---------------------------------------------------------------------------- cNaytto::~cNaytto() { kysy_talleta(); edit_vapauta("kerho.lyh"); }