Tietojenkäsittelytiede Harjoitustehtäviä Graafisten käyttöliittymien toteutus 31.1.2001 x1. +-------------------------------------------------------+ | Tämä tehtävä on pakollinen. | | | | Ratkaisu on lähetettävä sähköpostina osoitteella | | gkt01@cs.joensuu.fi viimeistään 30.1.2001 klo 8.00. | | | | ÄLÄ LÄHETÄ VASTAUSTA LIITETIEDOSTONA VAAN OSANA ITSE | | KIRJEEN TEKSTIÄ !!! | | | | Tuo harjoitustilaisuuteen ohjelmalistaus ja valmiiksi | | täyttämäsi x-tehtävän arviointilomake. | +-------------------------------------------------------+ Laadi C++:lla (n)curses-kirjastoa käyttävä merkkipohjainen (siis ei graafinen) ohjelma, joka antaa käyttäjän tehdä valintoja va- lintaruutujen ja valintanappien ryhmistä ja lopuksi tulostaa käyttäjän tekemät valinnat. Ohjelma on myös testattava. Valintaryhmien toiminnat ovat seuraavat: - Valintaruuturyhmä: Joukko vaihtoehtoja, joista kukin voi olla valittu (X) tai ei (_). Käyttäjä voi liikkua vaihtoehdosta toiseen näppäimillä NuoliYlös ja NuoliAlas ja vaihtaa valintatilaa näppäimellä En- ter. - Valintanappiryhmä: Joukko vaihtoehtoja, joista yksi on valittu (@) ja muut eivät ole (O). Käyttäjä voi liikkua vaihtoehdosta toiseen näppäimillä NuoliVasemmalle ja NuoliOikealle (vaikka vaihtoehdot ovatkin päällekkäin !) ja vaihtaa ny- kyisen vaihtoehdon valituksi näppäi- mellä Enter. Valintaryhmiä voi olla näytöllä mielivaltainen määrä ja käyttäjä pääsee ryhmästä seuraavaan näppäimellä Tab. Lisäksi numeroilla 1..9 pääsee suoraan ko. ryhmään (ja "suurinumeroisiin" ei tällä tavalla pääse). Ryhmät voivat sijaita näytöllä osittain päällek- käin ja ohjelman velvollisuus on "nostaa" kulloinkin käsiteltävä ryhmä näkyviin. Käyttäjä voi käydä kussakin ryhmässä niin monta kertaa kuin hän haluaa. Näppäimellä 'q' toiminta loppuu ja ohjel- ma tulostaa voimassaolevat valinnat. Näytölle tulevat valintaryhmät kuvataan tiedostossa, jossa on ku- takin ryhmää kohden: - rivi, jossa on ryhmän laji (r: ruutu, n: nappi) ja sen sijain- tipaikan vasemman yläkulman rivi ja sarake - kutakin vaihtoehtoa varten rivi, jossa on vaihtoehdon teksti - rivi, jolla on merkki '#' Tämä ohjaustiedosto voisi olla esimerkiksi seuraavanlainen: r 5 20 Musta Valkoinen Punainen Vaaleanvihreä # r 15 1 Aamiainen Lounas Päivällinen Iltapala Kahvit (2 kpl) # n 13 7 Puuvilla Pellava Villa Keinokuitu # r 15 50 Maljakko Vati # n 10 40 Kukka Vilja tms. # Edellisen ohjaustiedoston tapauksessa näyttö voisi olla käyttäjän tehtyä joitakin valintoja seuraavanlainen (reunoja leikattu pois): =================================================================== _ Musta X Valkoinen X Punainen _ Vaaleanvihreä @ Kukka O Vilja tms. O Puuvilla @ Pellava _ Aam O Villa _ Maljakko X Lou O Keinokuitu _ Vati _ Päivällinen X Iltapala X Kahvit (2 kpl) =================================================================== =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* Valintaryhmät on toteuttava olioina käyttäen seuraavaa liittymän määrittelyä: #define maxTeksti 80 #define MaxValintoja 10 /* ------------- Yläluokka valintaryhmille ------------- */ class ValintaRyhma { protected: /* ... */ public: /* Valintaryhmä muodostetaan antamalla muodostajalle parametreina valintaryhmän vasemman yläkulman koordinaatit ja kutsumalla ope- raatioita valinta kerran kutakin kyseiseen ryhmään kuuluvaa va- lintaa kohti. (Muodostajana käytetään tietenkin aliryhmän muodostajaa.) Esim: ryhma = new RuutuRyhma(5,15); virhe=ryhma->valinta("Vaihtoehto 1"); virhe=ryhma->valinta("Vaihtoehto 2"); virhe=ryhma->valinta("Vaihtoehto 3"); */ ValintaRyhma(int rivi, int sarake); virtual int valinta(char *teksti); // -1 jos virhe /* Valintaryhmää käytetään seuraavilla operaatioilla: piirry: Valintaryhmä tulostaa itsensä ruudulle ny- kyisillä valinnoilla. tuloRyhmään: Kursori on tulossa ryhmään. Operaatio si- joittaa kursorin ensimmäisen vaihtoehdon kohdalle. nappaily: Käyttäjä on painanut jotain näppäintä, jon- ka menetelmä saa parametrinaan. Operaation on muutettava valintojen ulkoasu vastaavas- ti ja sijoitettava kursori oikeaan kohtaan. Esim: ryhma->piirry(); ryhma->tuloRyhmaan(); ryhma->nappaily(ALAS); ryhma->nappaily(ALAS); ryhma->nappaily(ENTER); ryhma->nappaily(YLOS); ryhma->nappaily('x'); ryhma->nappaily(ENTER); ryhma->piirry(); ryhma->tuloRyhmaan(); */ virtual void piirry(); virtual void tuloRyhmaan(); virtual void nappaily(char c); /* Ryhmän voimassaolevia valintoja voi pyytää operaatioilla ensValittu ja seurValittu, jotka palauttavat parametrissaan osoittimen vaihtoehdon tekstiin ja omana arvonaan vaihtoehdon numeron tai -1 jos valintoja ei enää ole. Esim: ekaValinta = ryhma->ensValittu(valinnanTeksti1); if (ekaValinta >= 0) tokaValinta = ryhma->seurValittu(valinnanTeksti2); */ virtual int ensValittu(char *teksti); virtual int seurValittu(char *teksti); }; /* ------------- Valintaruutujen ryhmä ----------------- */ class RuutuRyhma : public ValintaRyhma { /* ... */ }; /* ------------- Valintanappien ryhmä ------------------ */ class NappiRyhma : public ValintaRyhma { /* ... */ }; =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* Curses-kirjastosta tarvitaan tässä tehtävässä vain hyvin pientä osaa. Seuraava esimerkki havainnollistaa kirjaston käyttöä: /* curses-esimerkki (ohjelma.cc) Ohjelman kääntäminen: gcc -o ohjelma ohjelma.cc -lcurses tai (ympäristöstä riippuen) gcc -o ohjelma ohjelma.cc -lcurses -ltermcap */ #include <curses.h> // curses-kirjasto #define ENTER 10 main () { char c; initscr(); cbreak(); noecho(); // Alusta curses mvprintw(5,20,"Paina jotain: "); refresh(); // Näytön päivitys if ((c=getch()) == ENTER) { move(10,0); printw("Painettu ENTER"); refresh(); } else { mvprintw(10,0,"Painettu %c",c); refresh(); } c=getch(); // Jotta kerkiäisi näkemään tulostuksen move(LINES-1,0); refresh(); endwin(); // Lopeta curses }