Okos térkép

Tegyük össze amit eddig tudunk:

Ami még hiányzik:

No, akkor kalandra fel! URL változó - az olyan, mint a city.

Ha meg megnyomják a gombot, az url-t úgy kell összerakni, hogy a city értéke a megfelelő helyen legyen:

url="http://maps.googleapis.com/maps/api/staticmap?center="+city+"&size=300x300&zoom=10";
public class MapWindow extends Form {

    String city="Budapest";
    String url="http://maps.googleapis.com/maps/api/staticmap?center=Budapest&size=300x300&zoom=10";

    final FieldString<MapWindow> CITY=FieldString.of(MapWindow.class,"city");
    final FieldString<MapWindow> URL=FieldString.of(MapWindow.class,"url");

    public MapWindow() {
        window()              
        .text("Térkép")        
        .add(
            group(
                edit(this,CITY),button(showAction)
            ),br(),
            view(this,URL).asPicture()
        )
        .show();                    
    }

    Action showAction=new Action("Mutasd") {
        @Override
        protected void execute() {
            url="http://maps.googleapis.com/maps/api/staticmap?center="+city+"&size=300x300&zoom=10";
        }
    };
}

Ez igazán csinos így! Észrevetted a group()-ot, amivel a szövegmező és a gomb egy csoportot képeznek, így a kép az egész csoport alá igazítja magát? Az is fontos, hogy induláskor az URL ne legyen üres. Ha üres az URL, akkor a view nem tud semmit betölteni, és nem tudja meghatározni a méretét, és akkor az egész ablak mérete nem számolható ki. Ezért beletettem Budapestet a városnévnek is, meg az URL-nek is, mint kezdőérték.

Térkép, bármiről!

Domborzat, műhold

Az URL-be további paramétereket is lehet tenni:

Akkor hát:

public class MapWindow extends Form {

    String city="Budapest";
    String url="http://maps.googleapis.com/maps/api/staticmap?center=Budapest&size=300x300&zoom=10";

    boolean terrain;

    final FieldString<MapWindow> CITY=FieldString.of(MapWindow.class,"city");
    final FieldString<MapWindow> URL=FieldString.of(MapWindow.class,"url");
    final FieldBoolean<MapWindow> TERRAIN=FieldBoolean.of(MapWindow.class,"terrain");

    public MapWindow() {
        window()              
        .text("Térkép")        
        .add(
            group(
                label("Város:"),edit(this,CITY),
                label("Domborzat:"),edit(this,TERRAIN),
                button(showAction)
            ),br(),
            view(this,URL).asPicture()
        )
        .show();                    
    }

    Action showAction=new Action("Mutasd") {
        @Override
        protected void execute() {
            url="http://maps.googleapis.com/maps/api/staticmap?center="+city+"&size=300x300&zoom=10";
            if (terrain) {
                url=url+"&maptype=terrain";
            }
        }
    };
}

Ó, azok a budai hegyek!

Fúú de jó! Figyelted, hogy csak edit-et kellett írni, és az edit kitalálta a változó típusából, hogy hogyan kell editálni? A stringes city-re szöveges editort rakott ki, a boolean-os terrainre meg egy checkbox-ot! Ez akkor azt jelenti, hogy Dulifuli listájáról ki lehet pipálni mégegy dolgot: nekünk nem kell megtanulni és fejben tartani, hogy épp hogyan nevezik azt a "be-ki pipálható izékét ma délután", hanem csak annyit mondunk, hogy edit, és hopsz, máris editál, bármit. A view meg megjelenít, bármit. (Néha lehet, hogy nem egyértelmű, mit kell csinálni, ezért a view például tudja ezt az .asPicture() dolgot, hogy a belerakott szöveget nem szövegként, hanem kép URLként kell értelmezni. De ez alapvetően ritka eset.)

Deklaratív programozás

Figyelted, hogy mit csináltunk itt? Csak elmondtuk a kívánságainkat, ide egy edit, ami ezt és ezt szerkeszti, oda egy view, ami ezt és ezt mutatja meg. Semmit nem rágtunk a gép szájába, csak kinyilvánítottuk, mit kívánunk. Ezt nevezik deklaratív programozásnak. (Ez fontos dolog, ezért beszélek róla újra, most, hogy jobban érzed az előnyeit.)

Imperatív: parancsoló, parancs alapú: lépésről lépésre elmondjuk, mit kell csinálni, és reményeink szerint ez megoldja a célt. A ma használt harmadik generációs nyelvek mind imperatívak (C, Pascal, C++, Java, Javascript).

Deklaratív: kinyilvánítás, szándék alapú: mi a célt mondjuk meg, nem pedig a cél eléréséhez szükséges lépéseket. Ezzel sokkal kevesebb programsorból sokkal áttekinthetőbben lehet programozni olyan dolgokat, amire ez a módszer értelmezhető. A ma használt negyedik generációs nyelvek deklaratívak (SQL), szintén deklaratívak a nem-programnyelvek (HTML - itt is csak azt mondjuk, hogy "ez itt egy fejléc", vagy a CSS "minden fejléc legyen sárga").

Deklaratív vagy imperatív a jobb?

A tapasztalat az, hogy néhány problémát nagyon kényelmes deklaratívan megoldani, más feladatokat viszont teljesen lehetetlen. Például, zenét hangokból lejátszani nem lehet deklaratívan, hiszen a zene arról szól, hogy egymás után sorban meg kell parancsolni, melyik hang következzen.

A mi programunkban is deklaratív volt az ablak kinézetének megadása, viszont imperatív volt a gomb megnyomására elinduló eseménykezelő kód.

Modern adatbázis rendszerekben egyszerre van deklaratív programozás az adatok kinyerésére (SQL) és imperatív programozás az adatok feldolgozására (Oracle: PL/SQL Microsoft SQL server: Transact SQL).

A deklaratív és az imperatív nyelvek ésszerű kombinálásával mindkét világ előnyös oldalát használhatjuk. Dulifuli azt mondja, ez megéri :)

A Java nem deklaratív programozási nyelv, hanem imperatív. Dulifuli ötletei alapján kitaláltuk, hogyan lehet egy kicsit kevesebbet szájbarágni, és egy kicsit többet kívánni - így most részben deklaratívan tudunk Java programot csinálni.

Mit tanultunk ebből?

Kevés kódból látványos program - deklaratív módszerekkel. Az edit() (és minden más factory method is) automatikusan olyan vezérlőket rak ki, ami az adott adattípussal értelmesen használható, így tulajdonképp csak annyit kell megjegyezni, hogy view, edit, button...