<?xml version="1.0" encoding="utf-8"?>
<page xmlns="http://projectmallard.org/1.0/" xmlns:its="http://www.w3.org/2005/11/its" xmlns:xi="http://www.w3.org/2001/XInclude" type="topic" style="task" id="03_getting_the_signal.js" lang="sv">
  <info>
    <link type="guide" xref="beginner.js#tutorials"/>
    <link type="seealso" xref="button.js"/>
    <link type="seealso" xref="entry.js"/>
    <link type="seealso" xref="radiobutton.js"/>
    <link type="seealso" xref="switch.js"/>
    <revision version="0.1" date="2012-08-12" status="draft"/>

    <credit type="author copyright">
      <name>Taryn Fox</name>
      <email its:translate="no">jewelfox@fursona.net</email>
      <years>2012</years>
    </credit>

    <desc>Skapa knappar och andra komponenter som gör saker när du klickar på dem.</desc>
  <credit type="translator copyright"><name>Sebastian Rasmussen</name><email>sebras@gmail.com</email><years>2019</years></credit><credit type="translator copyright"><name>Anders Jonsson</name><email>anders.jonsson@norsjovallen.se</email><years>2021</years></credit></info>

  <title>3. Få signalen</title>
  <synopsis>
    <p>I den senaste handledningen lärde vi oss hur man skapar komponenter så som Label, Image och Button. Här kommer vi att lära oss att få Button och andra inmatningskomponenter att faktiskt göra saker, genom att skriva funktioner som hanterar signalerna de skickar när de klickas på eller interageras med.</p>
  </synopsis>

  <links type="section"/>

  <section id="application">
    <title>Ett grundläggande program</title>
    <p>I GNOME skickar komponenter som du kan interagera med, så som Button och Switch, ut signaler när de klickas på eller aktiveras. En Button till exempel skickar ut signalen ”clicked” när någon klickar på den. När detta inträffar letar GNOME efter delen i din kod som säger vad som ska hända.</p>
    <p>Hur skriver vi den koden? Genom att ansluta Buttons ”clicked”-signal till en återanropsfunktion, vilket är en funktion du skriver enkom för att hantera den signalen. Så närhelst den signalen skickas ut kommer funktionen som är ansluten till den signalen att köra.</p>
    <p>Här är ett extremt enkelt exempel:</p>

    <media type="image" mime="image/png" src="media/03_jssignal_01.png"/>

    <p>Detta ApplicationWindow har en Button och en Label inuti, arrangerade via en Grid. Närhelst Button blir klickad på ökar en variabel som innehåller antalet kakor med ett och Labeln som visar hur många kakor det finns uppdateras.</p>
    <note style="tip"><p>Kakorna i detta exempel är inte samma som kakorna som du kan få från webbplatser, vilka lagrar din inloggningsinformation och håller reda på vilka webbplatser du besökt. De är bara fiktiva belöningar. Du kan baka några riktiga om du vill.</p></note>
    <p>Här är den grundläggande standardkoden som kör vid programmets start, innan vi börjar skapa fönstret och komponenter. Förutom att programmet har ett unikt namn är den största förändringen från standardkoden att vi skapar en global variabel precis i början för att lagra antalet kakor.</p>
    <code mime="application/javascript">
#!/usr/bin/gjs

imports.gi.versions.Gtk = '3.0';
const Gtk = imports.gi.Gtk;

// Vi börjar med 0 kakor
var cookies = 0;

class GettingTheSignal {
    // Skapa programmet i sig
    constructor() {
        this.application = new Gtk.Application();

        // Anslut ”active”- och ”startup”-signaler till återanropsfunktionerna
        this.application.connect('activate', this._onActivate.bind(this));
        this.application.connect('startup', this._onStartup.bind(this));
    }

    // Återanropsfunktion för ”activate”-signal, visar fönstret när den aktiveras
    _onActivate() {
        this._window.present();
    }

    // Återanropsfunktionen för ”startup”-signalen bygger användargränssnittet
    _onStartup() {
        this._buildUI ();
    }
</code>
    <p>Titta på delen som använder vårt programs anslutningsmetod och bindning för att ansluta dess ”activate”- och ”startup”-signaler till funktionerna som visar fönstret och bygger användargränssnittet. Vi kommer att göra samma sak med vår Button när vi kommer till det, förutom att vi kommer att ansluta dess ”clicked”-signal istället.</p>
  </section>

  <section id="button">
    <title>Klicka på knappen</title>

    <p>Som vanligt kommer vi att placera all kod för att skapa vår Button och andra komponenter inuti funktionen _buildUI, vilken anropas när programmet startar.</p>
    <code mime="application/javascript">
    // Bygg programmets användargränssnitt
    _buildUI() {
</code>

    <p>Först skapar vi fönstret i sig:</p>
    <code mime="application/javascript">
        // Skapa programfönstret
        this._window = new Gtk.ApplicationWindow({
            application: this.application,
            window_position: Gtk.WindowPosition.CENTER,
            default_height: 200,
            default_width: 400,
            title: "Klicka på knappen för att få en kaka!"});
</code>
    <p>Notera att vi har satt egenskaperna default_height och default_width. Dessa låter oss styra hur högt och brett, i bildpunkter, som ApplicationWindow kommer att vara.</p>
    <p>Härnäst kommer vi att skapa Labeln som visar oss antalet kakor. Vi kan använda kakvariabeln som en del av Labelns label-egenskap.</p>
    <code mime="application/javascript">
        // Skapa etiketten
        this._cookieLabel = new Gtk.Label ({
            label: "Antal kakor: " + cookies });
</code>

    <p>Nu skapar vi vår Button. Vi sätter dess label-egenskap så den visar texten som vi vill ha på vår Button, och vi ansluter dess ”clicked”-signal till en funktion kallad _getACookie, vilken vi kommer att skriva efter att vi är klara med att bygga vårt programs användargränssnitt.</p>
    <code mime="application/javascript">
        // Skapa kakknappen
        this._cookieButton = new Gtk.Button ({ label: "Få en kaka" });

        // Anslut kakknappen till funktionen som hanterar när den blir klickad på
        this._cookieButton.connect ('clicked', this._getACookie.bind(this));
</code>
    <p>Avslutningsvis skapar vi en Grid, fäster vår Label och Button till den och lägger till den till fönstret och ber fönstret att visa sig själv och sitt innehåll. Det är allt vi behöver göra inuti _buildUI-funktionen, så vi stänger den med en klammerparentes så väl som ett kommatecken som berättar för GNOME att fortsätta med nästa funktion. Notera att även om vi skrev koden för Label först kan vi fortfarande fästa den till Grid på ett sätt som placerar den längst ned.</p>
    <code mime="application/javascript">
        // Skapa ett rutnät för att ordna allting inuti
        this._grid = new Gtk.Grid ({
            halign: Gtk.Align.CENTER,
            valign: Gtk.Align.CENTER,
            row_spacing: 20 });

        // Placera allting inuti rutnätet
        this._grid.attach (this._cookieButton, 0, 0, 1, 1);
        this._grid.attach (this._cookieLabel, 0, 1, 1, 1);

        // Lägg till rutnätet till fönstret
        this._window.add (this._grid);

        // Visa fönstret och alla dess barnkomponenter
        this._window.show_all();

    }
</code>
    <p>Nu kommer vi att skriva _getACookie-funktionen. När vår Button skickar ut sin ”clicked”-signal kommer koden i denna funktion att köras. I detta fall är allt den ska göra att öka antalet kakor med 1 och uppdatera vår Label till att visa det nya antalet kakor. Vi gör detta via Labelns set_label-metod.</p>
    <note style="tip"><p>Många komponenter har samma egenskaper och metoder. Både Label och Button har till exempel en label-egenskap som säger vilken text som finns inuti dem, och get_label- och set_label-metoder som låter dig se vad texten är, respektive ändra den. Så om du lär dig hur en komponent fungerar kommer du också att veta hur andra liknande komponenter fungerar.</p></note>
    <code mime="application/javascript">
    _getACookie: function() {

        // Öka antalet kakor med 1 och uppdatera etiketten
        cookies++;
        this._cookieLabel.set_label ("Antal kakor: " + cookies);

    }

};
</code>

    <p>Avslutningsvis kör vi programmet med samma kod som i vår senaste handledning.</p>
    <code mime="application/javascript">
// Kör programmet
let app = new GettingTheSignal ();
app.application.run (ARGV);
</code>
  </section>

  <section id="switch">
    <title>Slå om brytaren</title>
    <p>Knappar är inte den enda typen av komponenter i GTK+-verktygslådan. Vi kan också använda brytare (Switch) som den i detta exempel. En Switch har inte en etikettegenskap, så vi måste skapa en separat Label intill som berättar vad den gör.</p>

    <media type="image" mime="image/png" src="media/03_jssignal_02.png"/>

    <p>En Switch har två positioner, av och på. När en Switch är påslagen kommer dess text och bakgrundsfärg att ändras, så du kan se vilken position den är i.</p>

    <p>Du kan ha sett Switchar som dessa i GNOME:s hjälpmedelsmeny, vilken låter dig slå på och av funktioner så som stor text och skärmtangentbord. I detta fall styr Switchen vår fiktiva kakautomat. Om Switchen är påslagen kan du få kakor genom att klicka på knappen ”Få en kaka”. Om den är avslagen, kommer klickande på knappen inte att göra något.</p>
    <note style="tip"><p>Du kan nå hjälpmedelsmenyn genom att klicka på konturen av en människa nära ditt namn i övre högra hörnet av skärmen.</p></note>
    <p>Så här skapar vi Switchen:</p>
    <code mime="application/javascript">
        // Skapa brytaren som styr huruvida du kan vinna eller ej
        this._cookieSwitch = new Gtk.Switch ();
</code>

    <p>Vi behöver faktiskt inte ansluta Switchen till någonting. Allt vi behöver göra är att skriva en if-sats i vår _getACookie-funktion, för att se om Switchen är påslagen. Om vi skulle vilja att något ska hända direkt när Switchen slås om, måste vi ansluta till dess notify::active-signal, så här:</p>
    <code mime="application/javascript">
        // Anslut brytaren till funktionen som hanterar den
        this._cookieSwitch.connect ('notify::active', this._cookieDispenser.bind(this));
</code>

    <p>En Switch är som standard satt till avslagen. Om vi vill att Switchen ska börja påslagen, måste vi sätta värdet för dess active-egenskap till true när vi skapar den.</p>
    <code mime="application/javascript">
        this._cookieSwitch = new Gtk.Switch ({ active: true });
</code>

    <p>Låt oss dock börja med att skapa den normalt, och sedan skapa en medföljande Label. Vi vill att Switchen och Labeln ska vara alldeles intill varandra, så vi skapar en Grid bara för dem, sedan stoppar vi denna Grid inuti vår större Grid som innehåller alla komponenterna. Här är hur koden skall se ut för allt detta:</p>
    <code mime="application/javascript">
        // Skapa brytaren som styr huruvida du kan vinna eller ej
        this._cookieSwitch = new Gtk.Switch ();

        // Skapa etiketten som medföljer brytaren
        this._switchLabel = new Gtk.Label ({
            label: "Kakautomat" });

        // Skapa ett rutnät för brytaren och dess etikett
        this._switchGrid = new Gtk.Grid ({
            halign: Gtk.Align.CENTER,
            valign: Gtk.Align.CENTER });

        // Stoppa brytaren och dess etikett inuti det rutnätet
        this._switchGrid.attach (this._switchLabel, 0, 0, 1, 1);
        this._switchGrid.attach (this._cookieSwitch, 1, 0, 1, 1);
</code>

    <p>Och nu arrangerar vi allting inuti vår större Grid på följande sätt.</p>
    <code mime="application/javascript">
        // Stoppa allting inuti rutnätet
        this._grid.attach (this._cookieButton, 0, 0, 1, 1);
        this._grid.attach (this._switchGrid, 0, 1, 1, 1);
        this._grid.attach (this._cookieLabel, 0, 2, 1, 1);
</code>

    <p>Nu ändrar vi _getACookie-funktionen så att den kontrollerar om kakautomaten är påslagen. Vi gör det genom att använda Switchens get_active-metod. Den returnerar true om Switchen är påslagen, och false om Switchen är avslagen.</p>
    <note style="tip"><p>När en metod används inuti en if-sats så här, kommer koden inuti if-satsen att köras om metoden returnerar true.</p></note>
    <code mime="application/javascript">
    _getACookie() {

        // Är kakautomaten påslagen?
        if (this._cookieSwitch.get_active()) {

            // Öka antalet kakor med 1 och uppdatera etiketten
            cookies++;
            this._cookieLabel.set_label ("Antal kakor: " + cookies);

        }

    }
</code>

  </section>

  <section id="radio">
    <title>Ratta på radion</title>

    <p>En annan sorts inmatningskomponent som vi kan använda kallas för RadioButton. Du skapar dem i grupper, och då kan endast en RadioButton i en grupp vara vald samtidigt. De kallas radioknappar för att de fungerar som knapparna för förinställda kanaler i en gammaldags bilradio. Radion kunde bara vara inställd på en kanal åt gången, så närhelst du tryckte på en knapp så fick det en annan att poppa ut igen.</p>

    <media type="image" mime="image/png" src="media/03_jssignal_03.png"/>

    <p>Låt oss först ändra namnet på vårt ApplicationWindow och öka dess border_width-egenskap, så att våra komponenter inte är så tätt packade. Värdet border_width är antalet bildpunkter mellan alla komponenter och fönstrets kant.</p>
    <code mime="application/javascript">
        // Skapa programfönstret
        this._window = new Gtk.ApplicationWindow({
            application: this.application,
            window_position: Gtk.WindowPosition.CENTER,
            default_height: 200,
            default_width: 400,
            border_width: 20,
            title: "Välj den som säger ”kaka”!"});
</code>

    <p>Efter det skapar vi RadioButton-knapparna. Kommer du ihåg att de skapas i grupper? Vi gör det genom att ställa in group-egenskapen för varje ny RadioButton till namnet på en annan RadioButton.</p>
    <code mime="application/javascript">
        // Create the radio buttons
        this._cookieRadio = new Gtk.RadioButton ({ label: "Kaka" });
        this._notCookieOne = new Gtk.RadioButton ({ label: "Inte kaka",
            group: this._cookieRadio });
        this._notCookieTwo = new Gtk.RadioButton ({ label: "Inte kaka",
            group: this._cookieRadio });
</code>

    <p>Härnäst skapar vi en Grid för RadioButton-knapparna. Kom ihåg att vi inte behöver arrangera saker i en Grid i samma ordning som vi skapar dem.</p>
    <code mime="application/javascript">
        // Arrangera radioknapparna i sitt eget rutnät
        this._radioGrid = new Gtk.Grid ();
        this._radioGrid.attach (this._notCookieOne, 0, 0, 1, 1);
        this._radioGrid.attach (this._cookieRadio, 0, 1, 1, 1);
        this._radioGrid.attach (this._notCookieTwo, 0, 2, 1, 1);
</code>

    <p>Vanligen är det den RadioButton som är vald som standard som används som namnet på gruppen. Vi vill dock att den första ”Inte kaka”-knappen ska vara vald som standard, så vi använder dess set_active-metod.</p>
    <note style="tip"><p>Vi skulle också kunna ställa in dess active-egenskap till true när vi skapar den.</p></note>
    <code mime="application/javascript">
        // Ställ in knappen högst upp att vara aktiv som standard
        this._notCookieOne.set_active (true);
</code>

    <p>Nu arrangerar vi allting i vår huvud-Grid som vanligt …</p>
    <code mime="application/javascript">
        // Stoppa allting inuti rutnätet
        this._grid.attach (this._radioGrid, 0, 0, 1, 1);
        this._grid.attach (this._cookieButton, 0, 1, 1, 1);
        this._grid.attach (this._cookieLabel, 0, 2, 1, 1);

</code>

    <p>Sedan ändrar vi vår _getACookie-funktion så att den testar om kakknappen är den som har valts.</p>
    <code mime="application/javascript">
    _getACookie() {

        // Valde du ”kaka” istället för ”inte kaka”?
        if (this._cookieRadio.get_active()) {

            // Öka antalet kakor med 1 och uppdatera etiketten
            cookies++;
            this._cookieLabel.set_label ("Antal kakor: " + cookies);

        }

    }
</code>

  </section>

  <section id="spell">
    <title>Kan du stava till ”kaka”?</title>

    <p>Den sista inmatningskomponenten som vi kommer att tala om är komponenten Entry, vilken används för textinmatningsfält med en ensam rad.</p>
    <note style="tip"><p>Om du behöver kunna mata in ett helt stycke eller mer, exempelvis om du bygger en textredigerare, så kommer du vilja ta en titt på den mycket mer anpassningsbara <link xref="textview.js">TextView</link>-komponenten.</p></note>
    <media type="image" mime="image/png" src="media/03_jssignal_04.png"/>

    <p>Efter att vi ändrar fönstrets namn skapar vi Entry-komponenten.</p>
    <code mime="application/javascript">
        // Skapa textinmatningsfältet
        this._spellCookie = new Gtk.Entry ();
</code>

    <p>Sedan arrangerar vi allt i vår Grid …</p>
    <code mime="application/javascript">
        // Stoppa allting inuti rutnätet
        this._grid.attach (this._spellCookie, 0, 0, 1, 1);
        this._grid.attach (this._cookieButton, 0, 1, 1, 1);
        this._grid.attach (this._cookieLabel, 0, 2, 1, 1);
</code>

    <p>Nu ändrar vi if-satsen för _getACookie igen, och använder get_text-metoden för Entryt för att få texten som du matade in i det och se om du stavade ”kaka” rätt. Vi bryr oss inte om du använder små eller stora bokstäver i ”kaka”, så vi använder Javascripts inbyggda toLowerCase-metod för att ändra texten för Entryt till gemener inuti if-satsen.</p>
    <note style="tip"><p>En Entry-komponent har ingen label-egenskap, vilket är en inställd textsträng som användaren inte kan ändra. (Du kan exempelvis vanligen inte ändra etiketten på en Button.) Istället har den en text-egenskap, vilken ändras så att den motsvarar vad användaren skriver in.</p></note>
    <code mime="application/javascript">
    _getACookie() {

        // Stavade du ”kaka” rätt?
        if ((this._spellCookie.get_text()).toLowerCase() == "kaka") {

            // Öka antalet kakor med 1 och uppdatera etiketten
            cookies++;
            this._cookieLabel.set_label ("Antal kakor: " + cookies);

        }

    }
</code>

  </section>

  <section id="whats_next">
    <title>Vad är nästa steg?</title>
    <p>Fortsätt läsa om du vill se den fullständiga koden för varje version av vårt kakmakarprogram.</p>
    <note style="tip"><p>Huvudsidan för Javascripthandledningar har <link xref="beginner.js#buttons">mer detaljerade kodexempel</link> för varje inmatningskomponent, däribland flera som inte täcks här.</p></note>

  </section>

  <section id="complete">
    <title>Fullständiga kodexempel</title>

    <links type="section"/>

    <section id="buttonsample">
      <title>Kodexempel med Button</title>
      <media type="image" mime="image/png" src="media/03_jssignal_01.png"/>
      <code mime="application/javascript" style="numbered">#!/usr/bin/gjs

imports.gi.versions.Gtk = '3.0';
const Gtk = imports.gi.Gtk;

// Vi börjar med 0 kakor
var cookies = 0;

class GettingTheSignal {

    // Skapa programmet i sig
    constructor() {
        this.application = new Gtk.Application();

        // Anslut ”activate”- och ”startup”-signaler till återanropsfunktionerna
        this.application.connect('activate', this._onActivate.bind(this));
        this.application.connect('startup', this._onStartup.bind(this));
    }

    // Återanropsfunktion för ”activate”-signal, visar fönstret när den aktiveras
    _onActivate() {
        this._window.present();
    }

    // Återanropsfunktion för ”startup”-signal bygger användargränssnittet
    _onStartup() {
        this._buildUI();
    }

    // Bytt programmets användargränssnitt
    _buildUI() {

        // Skapa programfönstret
        this._window = new Gtk.ApplicationWindow({
            application: this.application,
            window_position: Gtk.WindowPosition.CENTER,
            default_height: 200,
            default_width: 400,
            title: "Klicka på knappen för att få en kaka!"});

        // Skapa en etikett
        this._cookieLabel = new Gtk.Label ({
            label: "Antal kakor: " + cookies });

        // Skapa kak-knappen
        this._cookieButton = new Gtk.Button ({ label: "Få en kaka" });

        // Anslut kakknappen till funktionen som hanterar klickande på den
        this._cookieButton.connect ('clicked', this._getACookie.bind(this));

        // Skapa ett rutnät för att arrangera allting i
        this._grid = new Gtk.Grid ({
            halign: Gtk.Align.CENTER,
            valign: Gtk.Align.CENTER,
            row_spacing: 20 });

        // Stoppa allting inuti rutnätet
        this._grid.attach (this._cookieButton, 0, 0, 1, 1);
        this._grid.attach (this._cookieLabel, 0, 1, 1, 1);

        // Lägg till rutnätet till fönstret
        this._window.add (this._grid);

        // Visa fönstret och alla barnkomponenter
        this._window.show_all();

    }

    _getACookie() {

        // Öka antalet kakor med 1 och uppdatera etiketten
        cookies++;
        this._cookieLabel.set_label ("Antal kakor: " + cookies);

    }

};

// Kör programmet
let app = new GettingTheSignal ();
app.application.run (ARGV);
</code>
    </section>

    <section id="switchsample">
      <title>Kodexempel med Switch</title>
      <media type="image" mime="image/png" src="media/03_jssignal_02.png"/>
      <code mime="application/javascript" style="numbered">#!/usr/bin/gjs

imports.gi.versions.Gtk = '3.0';
const Gtk = imports.gi.Gtk;

// Vi börjar med 0 kakor
var cookies = 0;

class GettingTheSignal {

    // Skapa programmet i sig
    constructor() {
        this.application = new Gtk.Application();

        // Anslut ”activate”- och ”startup”-signaler till återanropsfunktionerna
        this.application.connect('activate', this._onActivate.bind(this));
        this.application.connect('startup', this._onStartup.bind(this));
    }

    // Återanropsfunktion för ”activate”-signal, visar fönstret när den aktiveras
    _onActivate() {
        this._window.present();
    }

    // Återanropsfunktion för ”startup”-signal bygger användargränssnittet
    _onStartup() {
        this._buildUI();
    }

    // Bygg programmets användargränssnitt
    _buildUI() {

        // Skapa programfönstret
        this._window = new Gtk.ApplicationWindow({
            application: this.application,
            window_position: Gtk.WindowPosition.CENTER,
            default_height: 200,
            default_width: 400,
            title: "Klicka på knappen för att få en kaka!"});

        // Skapa etiketten
        this._cookieLabel = new Gtk.Label ({
            label: "Antal kakor: " + cookies });

        // Skapa kak-knappen
        this._cookieButton = new Gtk.Button ({
            label: "Få en kaka" });

        // Anslut kakknappen till funktionen som hanterar klickande på den
        this._cookieButton.connect ('clicked', this._getACookie.bind(this));

        // Skapa en brytare som styr huruvida du kan vinna eller ej
        this._cookieSwitch = new Gtk.Switch ();

        // Skapa etiketten som följer med brytaren
        this._switchLabel = new Gtk.Label ({
            label: "Kakautomat" });

        // Skapa ett rutnät för brytaren och dess etikett
        this._switchGrid = new Gtk.Grid ({
            halign: Gtk.Align.CENTER,
            valign: Gtk.Align.CENTER });

        // Stoppa brytaren och dess etikett inuti det rutnätet
        this._switchGrid.attach (this._switchLabel, 0, 0, 1, 1);
        this._switchGrid.attach (this._cookieSwitch, 1, 0, 1, 1);

        // Skapa ett rutnät för att arrangera allting annat inuti
        this._grid = new Gtk.Grid ({
            halign: Gtk.Align.CENTER,
            valign: Gtk.Align.CENTER,
            row_spacing: 20 });

        // Stoppa allting inuti rutnätet
        this._grid.attach (this._cookieButton, 0, 0, 1, 1);
        this._grid.attach (this._switchGrid, 0, 1, 1, 1);
        this._grid.attach (this._cookieLabel, 0, 2, 1, 1);

        // Lägg till rutnätet till fönstret
        this._window.add (this._grid);

        // Visa fönstret och alla dess barnkomponenter
        this._window.show_all();

    }

    _getACookie() {

        // Är kakautomaten påslagen?
        if (this._cookieSwitch.get_active()) {

            // Öka antalet kakor med 1 och uppdatera etiketten
            cookies++;
            this._cookieLabel.set_label ("Antal kakor: " + cookies);

        }

    }

};

// Kör programmet
let app = new GettingTheSignal ();
app.application.run (ARGV);
</code>
    </section>

    <section id="radiobuttonsample">
      <title>Kodexempel med RadioButton</title>
      <media type="image" mime="image/png" src="media/03_jssignal_03.png"/>
      <code mime="application/javascript" style="numbered">#!/usr/bin/gjs

imports.gi.versions.Gtk = '3.0';
const Gtk = imports.gi.Gtk;

// Vi börjar med 0 kakor
var cookies = 0;

class GettingTheSignal {

    // Skapa programmet i sig
    constructor() {
        this.application = new Gtk.Application();

        // Anslut ”activate”- och ”startup”-signaler till återanropsfunktionerna
        this.application.connect('activate', this._onActivate.bind(this));
        this.application.connect('startup', this._onStartup.bind(this));
    }

    // Återanropsfunktion för ”activate”-signal, visar fönstret när den aktiveras
    _onActivate() {
        this._window.present();
    }

    // Återanropsfunktion för ”startup”-signal bygger användargränssnittet
    _onStartup() {
        this._buildUI();
    }

    // Bygg användargränssnittet
    _buildUI() {

        // Skapa programfönstret
        this._window = new Gtk.ApplicationWindow({
            application: this.application,
            window_position: Gtk.WindowPosition.CENTER,
            default_height: 200,
            default_width: 400,
            border_width: 20,
            title: "Välj den som säger ”kaka”!"});

        // Skapa radioknapparna
        this._cookieRadio = new Gtk.RadioButton ({ label: "Kaka" });
        this._notCookieOne = new Gtk.RadioButton ({ label: "Inte kaka",
            group: this._cookieRadio });
        this._notCookieTwo = new Gtk.RadioButton ({ label: "Inte kaka",
            group: this._cookieRadio });

        // Arrangera radioknapparna i sitt eget rutnät
        this._radioGrid = new Gtk.Grid ();
        this._radioGrid.attach (this._notCookieOne, 0, 0, 1, 1);
        this._radioGrid.attach (this._cookieRadio, 0, 1, 1, 1);
        this._radioGrid.attach (this._notCookieTwo, 0, 2, 1, 1);

        // Ställ in knappen högst upp att vara aktiv som standard
        this._notCookieOne.set_active (true);

        // Skapa kakknappen
        this._cookieButton = new Gtk.Button ({
            label: "Få en kaka" });

        // Anslut kakknappen till funktionen som hanterar klickande på den
        this._cookieButton.connect ('clicked', this._getACookie.bind(this));

        // Skapa etiketten
        this._cookieLabel = new Gtk.Label ({
            label: "Antal kakor: " + cookies });

        // Skapa ett rutnät för att arrangera allt inuti
        this._grid = new Gtk.Grid ({
            halign: Gtk.Align.CENTER,
            valign: Gtk.Align.CENTER,
            row_spacing: 20 });

        // Stoppa allting inuti rutnätet
        this._grid.attach (this._radioGrid, 0, 0, 1, 1);
        this._grid.attach (this._cookieButton, 0, 1, 1, 1);
        this._grid.attach (this._cookieLabel, 0, 2, 1, 1);

        // Lägg till rutnätet till fönstret
        this._window.add (this._grid);

        // Visa fönstret och alla barnkomponenter
        this._window.show_all();

    }

    _getACookie() {

        // Valde du ”kaka” istället för ”inte kaka”?
        if (this._cookieRadio.get_active()) {

            // Öka antalet kakor med 1 och uppdatera etiketten
            cookies++;
            this._cookieLabel.set_label ("Antal kakor: " + cookies);

        }

    }

};

// Kör programmet
let app = new GettingTheSignal ();
app.application.run (ARGV);
</code>
    </section>

    <section id="entrysample">
      <title>Kodexempel med Entry</title>
      <media type="image" mime="image/png" src="media/03_jssignal_04.png"/>
      <code mime="application/javascript" style="numbered">#!/usr/bin/gjs

imports.gi.versions.Gtk = '3.0';
const Gtk = imports.gi.Gtk;

// Vi börjar med 0 kakor
var cookies = 0;

class GettingTheSignal {

    // Skapa programmet i sig
    constructor() {
        this.application = new Gtk.Application();

        // Anslut ”activate”- och ”startup”-signaler till återanropsfunktionerna
        this.application.connect('activate', this._onActivate.bind(this));
        this.application.connect('startup', this._onStartup.bind(this));
    }

    // Återanropsfunktion för ”activate”-signal, visar fönstret när den aktiveras
    _onActivate() {
        this._window.present();
    }

    // Återanropsfunktion för ”startup”-signal bygger användargränssnittet
    _onStartup() {
        this._buildUI();
    }

    // Bygg användargränssnittet
    _buildUI() {

        // Skapa programfönstret
        this._window = new Gtk.ApplicationWindow({
            application: this.application,
            window_position: Gtk.WindowPosition.CENTER,
            default_height: 200,
            default_width: 400,
            border_width: 20,
            title: "Stava till ”kaka” för att få en kaka!"});

        // Skapa textinmatningsfältet
        this._spellCookie = new Gtk.Entry ();

        // Skapa kakknappen
        this._cookieButton = new Gtk.Button ({
            label: "Få en kaka" });

        // Anslut kakknappen till funktionen som hanterar klickande på den
        this._cookieButton.connect ('clicked', this._getACookie.bind(this));

        // Skapa etiketten
        this._cookieLabel = new Gtk.Label ({
            label: "Antal kakor: " + cookies });

        // Skapa ett rutnät för att arrangera allt inuti
        this._grid = new Gtk.Grid ({
            halign: Gtk.Align.CENTER,
            valign: Gtk.Align.CENTER,
            row_spacing: 20 });

        // Stoppa allting inuti rutnätet
        this._grid.attach (this._spellCookie, 0, 0, 1, 1);
        this._grid.attach (this._cookieButton, 0, 1, 1, 1);
        this._grid.attach (this._cookieLabel, 0, 2, 1, 1);

        // Lägg till rutnätet till fönstret
        this._window.add (this._grid);

        // Visa fönstret och alla barnkomponenter
        this._window.show_all();

    }

    _getACookie() {

        // Stavade du ”kaka” rätt?
        if ((this._spellCookie.get_text()).toLowerCase() == "kaka") {

            // Öka antalet kakor med 1 och uppdatera etiketten
            cookies++;
            this._cookieLabel.set_label ("Antal kakor: " + cookies);

        }

    }

};

// Kör programmet
let app = new GettingTheSignal ();
app.application.run (ARGV);
</code>
    </section>

  </section>

</page>
