<?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="02_welcome_to_the_grid.js" xml:lang="pt-BR">
  <info>
    <link type="guide" xref="beginner.js#tutorials"/>
    <link type="seealso" xref="grid.js"/>
    <link type="seealso" xref="image.js"/>
    <link type="seealso" xref="label.js"/>
    <revision version="0.1" date="2012-07-28" status="draft"/>

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

    <desc>Aprenda como posicionar componentes de interface de usuário, como Images e Labels.</desc>
  
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
      <mal:name>Rafael Ferreira</mal:name>
      <mal:email>rafael.f.f1@gmail.com</mal:email>
      <mal:years>2013</mal:years>
    </mal:credit>
  </info>

  <title>2. Bem-vindo à Grid</title>
  <synopsis>
    <p>Este tutorial vai mostrar a você como criar widgets básicos ou partes da interface de usuário do GNOME, como Images (imagens) e Labels (rótulos). Você, então, aprenderá como organizá-las em uma Grid (grade), que permite que você coloca widgets exatamente onde você os quer.</p>
    <note style="warning"><p>Você já viu <link xref="hellognome.js">o primeiro tutorial desta série</link>? Você vai querer vê-lo antes de continuar.</p></note>
  </synopsis>

  <links type="section"/>

  <section id="native">
    <title>Se tornando nativo</title>

    <p>No último tutorial, nós criamos o que era basicamente um quadro de janela do GNOME para um aplicativo web. Todo o código específico do GNOME que nós precisamos aprender se resolver colocando o WebView -- o widget contendo nosso aplicativo -- em um ApplicationWindow, e falando para ele exibir. O aplicativo em si foi escrito em HTML e JavaScript, assim como a maioria das páginas na web.</p>
    <p>Agora, nós vamos usar apenas widgets nativos do GNOME. Um widget é apenas uma coisa, como uma caixa de seleção ou imagem, e o GNOME tem uma ampla variedade delas para se escolher. Nós chamamos elas de widgets "nativas" para diferenciá-las de coisas como o botão e cabeçalho nos aplicativos web que nós escrevemos. Porque em vez de usarmos código web, essas vão ser 100 porcento GNOME, usando o GTK+.</p>
    <note style="tip"><p>GTK+ significa "GIMP Toolkit" (kit de ferramentas do GIMP). É como uma caixa de ferramentas de widgets que você pode acessar, enquanto construindo seus aplicativos. Ele foi escrito originalmente para <link href="http://www.gimp.org/">o GIMP</link>, que é um software livre de edição de imagens.</p></note>
  </section>

  <section id="setup">
    <title>Configurando seu aplicativo</title>

    <p>Antes de nos aprofundarmos na caixa de ferramentas do GTK+, nós primeiro precisamos escrever o código básico padrão que nosso aplicativo requer.</p>
    <code mime="application/javascript">
#!/usr/bin/gjs

const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
</code>
    <p>Essa parte sempre vai no começo do seu código. Dependendo do que você vai fazer com ele, você pode querer declarar muitas importações aqui. O que nós estamos escrevendo hoje é bem básico, de forma que isso é tudo que precisamos; o Gtk para os widgets, e Lang de forma que nós possamos usar o Lang.bind para conectar os sinais de ativação e inicialização de nosso aplicativo para requisitar funções.</p>
    <p>Falando nisso:</p>
    <code mime="application/javascript">
const WelcomeToTheGrid = new Lang.Class({
    Name: 'Bem-vindo à Grid',

    // Cria o aplicativo em si
    _init: function() {
        this.application = new Gtk.Application();

        // Conecta os sinais 'activate' e 'startup' para as funções de chamada
        this.application.connect('activate', Lang.bind(this, this._onActivate));
        this.application.connect('startup', Lang.bind(this, this._onStartup));
    },

    // Função de chamada para o sinal 'activate' apresenta janelas quando ativa
    _onActivate: function() {
        this._window.present();
    },

    // Função de chamada para sinal 'startup' constrói a interface gráfica
    _onStartup: function() {
        this._buildUI ();
    },
</code>
    <p>Esse é o começo de um aplicativo em si e a função _init que cria-o. Ela fala para _buildUI criar um ApplicationWindow, com o qual nós vamos chamar _window, e fala para nossa janela para se apresentar quando for necessário.</p>
    <p>Essa parte, de novo, é basicamente um copia-e-cola, mas você sempre deseja dar seu aplicativo um nome único.</p>

    <code mime="application/javascript">
    // Constrói a interface gráfica do aplicativo
    _buildUI: function() {

        // Cria a janela do aplicativo
        this._window = new Gtk.ApplicationWindow({
            application: this.application,
            window_position: Gtk.WindowPosition.CENTER,
            border_width: 10,
            title: "Bem-vindo à Grid"});
</code>
    <p>Finalmente, nós começamos a função _buildUI criando uma nova ApplicationWindow. Nós especificamos que ela vai com este aplicativo, que ela deveria aparecer no centro da tela, e que deve haver pelo menos 10 pixels entre a borda exterior e quaisquer widgets dentro dela. Nós também damos a ela um título, que vai aparecer no topo da janela.</p>
  </section>

  <section id="toolbox">
    <title>Alcançando a caixa de ferramentas do GTK+</title>
    <p>Quais widgets nós deveríamos usar? Bem, digamos que nós queremos escrever um aplicativo que se parece com este:</p>

    <media type="image" mime="image/png" src="media/02_jsgrid_01.png"/>

    <p>Nós vamos precisar, no mínimo, de uma imagem e um rótulo de texto para seguir. Vamos começar com a imagem:</p>
    <code mime="application/javascript">
        // Cria uma imagem
        this._image = new Gtk.Image ({ file: "gnome-image.png" });
</code>

    <p>Você pode baixar o arquivo de imagem neste exemplo <link href="https://live.gnome.org/TarynFox?action=AttachFile&amp;do=get&amp;target=gnome-image.png">arquivo</link>. Certifique-se de colocá-lo no mesmo diretório do código que você está escrevendo.</p>

    <code mime="application/javascript">
        // Cria um rótulo
        this._label = new Gtk.Label ({ label: "Bem-vindo ao GNOME, também!" });
</code>
    <p>Aquele código adiciona o rótulo abaixo. Você pode ver como nós criamos widgets aqui; cada um é uma parte do GTK e nós podemos dar a ele propriedades que personalizam como ele se comporta. neste caso, nós definimos a propriedade do arquivo de imagem para ser o nome do arquivo da imagem que queremos e adicionamos a propriedade de rótulo do Label para ser a sentença que desejamos embaixo da imagem.</p>
    <note style="tip"><p>Sim, isso soa redundante um Label ter uma propriedade de rótulo, mas não é. Outros widgets que contêm texto possuem uma propriedade de rótulo, de forma que é <em>consistente</em> para o widget de Label ter um também.</p></note>
    <p>Nós não podemos simplesmente adicionar estes widgets a nossa janela em ordem, porém, da mesma forma que elementos HTML aparecem na ordem que você escreve-os. Isso porque em ApplicationWindow pode conter apenas um widget.</p>
    <p>Como nós resolvemos isso? Marcando aquele widget como um widget contêiner, que pode manter mais de um widget e organizá-los dentro dele. Conheça: a Grid.</p>
    <code mime="application/javascript">
        // Cria a Grid
        this._grid = new Gtk.Grid ();
</code>

    <p>Nós não estamos desistindo de nenhuma propriedade ainda. Aquelas virão posteriormente, na medida em que aprendemos como usar os poderes da Grid. Primeiro, vamos anexar a Image e Label que nós fizemos para nossa Grid.</p>
    <code mime="application/javascript">
        // Anexa a imagem e o rótulo à grade
        this._grid.attach (this._image, 0, 0, 1, 1);
        this._grid.attach (this._label, 0, 1, 1, 1);
</code>

    <p>Este código parece muito complicado, mas não é. Aqui segue o que aqueles números significam:</p>
    <list type="numbered">
      <item><p>O <em>primeiro</em> número é qual posição esquerda-para-direita deve-se coloca as coisas, começando de 0. Qualquer widget que usa um 0 aqui vai para o mais esquerda possível.</p></item>
      <item><p>O <em>segundo</em> número é qual posição de cima-para-baixo deve-se colocar uma dado widget, começando de 0. O Label vai embaixo da Image, de forma que nós damos à Image um 0 e o Label um 1 aqui.</p></item>
      <item><p>O <em>terceiro</em> e <em>quarto</em> números são quantas colunas e linhas um widget deveria levar. Nós vamos ver como estes funcionam em um minuto.</p></item>
    </list>

    <code mime="application/javascript">
        // Adiciona a grade à janela
        this._window.add (this._grid);

        // Mostra a janela e todos seus widgets filhos
        this._window.show_all();
    }

});

// Executa o aplicativo
let app = new WelcomeToTheGrid ();
app.application.run (ARGV);
</code>
    <p>Agora que nós criamos a Grid e anexamos todos os nossos widgets a ela, nós adicionamos-a à janela e falamos para a janela se mostrar, como parte da função _buildUI. Como sempre, para finalizar nós criamos uma nova instância da classe do aplicativo e falamos para ele executar.</p>
    <p>Salva seu aplicativo como welcome_to_the_grid.js. Então, para executar seu aplicativo basta abrir um terminal, ir até o diretório onde seu aplicativo se encontra e digitar</p>
      <screen> <output style="prompt">$ </output>gjs welcome_to_the_grid.js </screen>

    <media type="image" mime="image/png" src="media/02_jsgrid_02.png"/>

    <p>Pronto! Mas espera. Isso não parece correto. Por que o Label está misturado próximo à Image desta forma? Isso não ficou legal e fica mais difícil de ler. O que nós podemos fazer quanto a isso?</p>
  </section>

  <section id="tweaking">
    <title>Ajustando a Grid</title>

    <p>Uma coisa que nós podemos fazer é dar ao Label uma propriedade margin_top no momento de sua criação. Isso funciona mais ou menos como definir uma margem para um elemento HTML usando estilo CSS embutido.</p>
    <code mime="application/javascript">
        // Cria um rótulo
        this._label = new Gtk.Label ({
            label: "Bem-vindo ao GNOME, também!",
            margin_top: 20 });
</code>

    <p>É claro que, se nós fizermos isso, então se substituirmos a Label com alguma outra coisa -- ou adicionar em outro widget --, então nós teremos que repetir o margin_top nele também. Do contrário, nós acabaremos com alguma coisa como isso:</p>
    <media type="image" mime="image/png" src="media/02_jsgrid_03.png"/>

    <p>Nós poderíamos dar à Image uma propriedade margin_bottom, mas isso não vai funcionar quando a nova Label estiver em uma coluna separada. Então, que tal nós tentarmos isso:</p>
    <code mime="application/javascript">
        // Cria a Grid
        this._grid = new Gtk.Grid ({
            row_spacing: 20 });
</code>

    <p>Isso resolve, de forma que há sempre 20 pixels de espaço entre cada linha horizontal.</p>
    <note style="tip"><p>Sim, você também pode definir a propriedade column_spacing em uma Grid ou as propriedades margin_left e margin_right em qualquer widget. Tente-os, se você quiser!</p></note>
  </section>

  <section id="adding">
    <title>Adicionando mais widgets</title>

    <p>Se nós quiséssemos adicionar um segundo Label, como que nós vamos fazê-lo de forma que ela realmente pareça como pertencente dali? Uma forma é centralizar a Image na parte superior, de forma que esteja em cima de ambas Labels, em vez de apenas uma para a esquerda. É aí que aqueles outros números no método para anexar na Grid entram:</p>
    <code mime="application/javascript">
        // Cria um segundo rótulo
        this._labelTwo = new Gtk.Label ({
            label: "O bolo é uma torta." });

        // Anexa a imagem e rótulos à grade
        this._grid.attach (this._image, 0, 0, 2, 1);
        this._grid.attach (this._label, 0, 1, 1, 1);
        this._grid.attach (this._labelTwo, 1, 1, 1, 1);
</code>

    <p>Após termos criado um segundo Label, nós o anexamos o segundo Label, o anexamos à Grid à direita do primeiro Label. Lembre-se, os primeiros dois números contam colunas e linhas da esquerda para a direita e de cima para baixo, começando com 0. Então, se o primeiro Label está na coluna 0 e linha 1, nós podemos colocar o segundo na coluna 1 e linha 1 para colocá-lo à direita do primeiro Label.</p>
    <p>Note que o número 2 na declaração de anexação para a Image. É o que faz o truque aqui. Aquele número é quantas colunas uma Image se estende, lembra-se? Então, quando nós colocarmos isso junto, nós obteremos algo tipo isso:</p>
    <media type="image" mime="image/png" src="media/02_jsgrid_04.png"/>

    <p>Há duas coisas das quais você deveria tomar nota, aqui.</p>
    <list>
      <item><p>A definição da Image para se estender a duas colunas não estica a imagem em si horizontalmente. Ao invés disso, ela estica a caixa invisível utilizadas pelo widget da Image para preencher ambas colunas e, então, colocar a imagem no centro daquela caixa.</p></item>
      <item><p>Ainda que tenhamos definido as propriedades row_spacing da Grid e border_width da ApplicationWindow, nós ainda não definimos nada que coloque uma borda entre as duas Labels. Elas estavam separadas anteriormente, quando a Imagem estava apenas em uma coluna, mas agora que ela estende ambas, o GNOME não vê um motivo para mantê-los separados.</p></item>
    </list>

    <p>Há pelo menos três formas de resolvermos o último. Primeiro, nós podemos definir um margin_left ou margin_right em um dos Labels:</p>
    <media type="image" mime="image/png" src="media/02_jsgrid_05.png"/>

    <p>Segundo, nós podemos definir a propriedade column_homogenous da Grid para "true".</p>
    <code mime="application/javascript">
        // Cria a Grid
        this._grid = new Gtk.Grid ({
            column_homogeneous: true,
            row_spacing: 20 });
</code>

    <p>Isso faz com que ela se pareça com algo como isso:</p>
    <media type="image" mime="image/png" src="media/02_jsgrid_06.png"/>

    <p>E terceiro, nós podemos definir a propriedade column_spacing da Grid, da mesma forma que nós definimos sua row_spacing.</p>
    <code mime="application/javascript">
        // Cria a Grid
        this._grid = new Gtk.Grid ({
            column_spacing: 20,
            row_spacing: 20 });
</code>
    <p>Isso faz com que ela se pareça com isso:</p>
    <media type="image" mime="image/png" src="media/02_jsgrid_07.png"/>
  </section>

  <section id="stock">
    <title>Usando imagens padrões</title>

    <p>O GNOME já possui um monte de imagens padrões em mãos, que nós podemos usar se não quisermos criar nossa própria ou se nós quisermos um ícone reconhecido universalmente. Aqui está como nós criamos imagens padrões, comparado com como nós criamos um normal:</p>
    <code mime="application/javascript">
        // Cria uma imagem
        this._image = new Gtk.Image ({ file: "gnome-image.png" });

        // Cria uma segunda imagem usando o ícone padrão
        this._icon = new Gtk.Image ({ stock: 'gtk-about' });
</code>
    <p>Após isso, nós anexamos-o à Grid à esquerda do primeiro Label. (Nós não vamos usar o segundo para este exemplo.)</p>
    <code mime="application/javascript">
        // Anexa as imagens e rótulos à grade
        this._grid.attach (this._image, 0, 0, 2, 1);
        this._grid.attach (this._icon,  0, 1, 1, 1);
        this._grid.attach (this._label, 1, 1, 1, 1);
</code>
    <p>Isso nos dá isso, quando nós o executamos:</p>
    <media type="image" mime="image/png" src="media/02_jsgrid_08.png"/>

    <p>É assim que o ícone padrão "Sobre" se parece. Você pode ver uma lista de todos os itens padrões começando com o gtk-about na <link href="https://developer.gnome.org/gtk3/3.4/gtk3-Stock-Items.html#GTK-STOCK-ABOUT:CAPS">documentação de desenvolvimento do GNOME</link>. Foi escrita para programadores de C, mas você não precisa saber C para usá-la; basta olha na parte nos sinais de citação, como "gtk-about" e copiar aquela parte para usar o ícone ao lado dele.</p>
    <note style="tip"><p>Nós colocamos aspas simples em volta de 'gtk-about' aqui porque, ao contrário de strings de texto que têm aspas duplas em volta, aquela parte nunca precisará ser traduzida para outro idioma. Na verdade, se ela <em>fosse</em> traduzida, ela quebraria o ícone porque seu nome ainda é "gtk-about" independentemente do seu idioma.</p></note>
  </section>


  <section id="next">
    <title>O que vem em seguida?</title>
    <p>Antes de irmos para o próximo tutorial, vamos tentar algo um pouco diferente:</p>
    <code mime="application/javascript">
        // Cria um botão
        this._button = new Gtk.Button ({
            label: "Bem-vindo ao GNOME, também!"});

        // Anexa as imagens e botão à grade
        this._grid.attach (this._image,  0, 0, 2, 1);
        this._grid.attach (this._icon,   0, 1, 1, 1);
        this._grid.attach (this._button, 1, 1, 1, 1);
</code>

    <p>É isso mesmo, nós tornamos o Label em um Button apenas alterando o seu nome! Se você executar o aplicativo e clicar nele, porém, você descobrirá que ele faz nada. Como nós vamos fazer nosso Button fazer algo? É o que vamos descobrir, em <link xref="03_getting_the_signal.js">nosso próximo tutorial</link>.</p>
    <p>Se você quiser, sinta-se à vontade para gastar algum tempo experimentando Grids, Labels e Images, incluindo imagens padrões.</p>
    <note style="tip"><p>Um truque que você pode usar para fazer layouts mais complexos é aninhar Grids dentro de Grids. Isso permite que você agrupe widgets relacionados e rearranje-os facilmente. Dê uma olhada na amostra de código do <link xref="radiobutton.js">RadioButton</link>, se você quiser ver como ele é feito.</p></note>
  </section>

  <section id="complete">
    <title>Amostra de código completo</title>
<code mime="application/javascript" style="numbered">#!/usr/bin/gjs

const Gtk = imports.gi.Gtk;
const Lang = imports.lang;

const WelcomeToTheGrid = new Lang.Class({
    Name: 'Bem-vindo à Grid',

    // Cria o aplicativo em si
    _init: function() {
        this.application = new Gtk.Application();

    // Conecta os sinais 'activate' e 'startup' às funções de chamada
    this.application.connect('activate', Lang.bind(this, this._onActivate));
    this.application.connect('startup', Lang.bind(this, this._onStartup));
    },

    // Função de chamada para o sinal 'activate' apresenta janelas quando ativo
    _onActivate: function() {
        this._window.present();
    },

    // Função de chamada para o sinal 'startup' constrói a interface gráfica
    _onStartup: function() {
        this._buildUI ();
    },



    // Constrói a interface gráfica do aplicativo
    _buildUI: function() {

        // Cria a janela do aplicativo
        this._window = new Gtk.ApplicationWindow({
            application: this.application,
            window_position: Gtk.WindowPosition.CENTER,
            border_width: 10,
            title: "Bem-vindo à Grid"});

        // Cria a Grid
        this._grid = new Gtk.Grid ({
            // column_homogeneous: true,
            // column_spacing: 20,
            row_spacing: 20 });

        // Cria uma imagem
        this._image = new Gtk.Image ({ file: "gnome-image.png" });

        // Cria uma segunda imagem usando um ícone padrão
        this._icon = new Gtk.Image ({ stock: 'gtk-about' });

        // Cria um rótulo
        this._label = new Gtk.Label ({
            label: "Bem-vindo ao GNOME, também!",
            /* margin_top: 20 */ });

        /* Cria um segundo rótulo
        this._labelTwo = new Gtk.Label ({
            label: "O bolo é uma torta." }); */

        /* Cria um botão
        this._button = new Gtk.Button ({
            label: "Bem-vindo ao GNOME, também!"}); */

        // Anexa as imagens e botão à grade
        this._grid.attach (this._image,  0, 0, 2, 1);
        this._grid.attach (this._icon,   0, 1, 1, 1);
        this._grid.attach (this._label,  1, 1, 1, 1);

        // this._grid.attach (this._label, 0, 1, 1, 1);
        // this._grid.attach (this._labelTwo, 1, 1, 1, 1);

        // this._grid.attach (this._button, 1, 1, 1, 1);

        // Adiciona a grade à janela
        this._window.add (this._grid);

        // Mostra a janela e todos os widgets filhos
        this._window.show_all();
    }

});

// Executa o aplicativo
let app = new WelcomeToTheGrid ();
app.application.run (ARGV);
</code>
  </section>

</page>
