O Leonardo Machado http://ptbr.oleonardomachado.com Desenvolvimento de Software (Dotnet, Android, Windows Phone etc) Tue, 10 Feb 2015 15:56:02 +0000 pt-BR hourly 1 http://wordpress.org/?v=4.1 Executando código dinamicamente em .NET – Compilando Código C# em Runtime http://ptbr.oleonardomachado.com/2015/02/10/executando-codigo-dinamicamente-em-net-compilando-codigo-c-em-runtime/ http://ptbr.oleonardomachado.com/2015/02/10/executando-codigo-dinamicamente-em-net-compilando-codigo-c-em-runtime/#comments Tue, 10 Feb 2015 15:56:02 +0000 http://ptbr.oleonardomachado.com/?p=95 Em um projeto recente do qual participei, tive a necessidade de alterar partes do codigo de forma extremamente rápida devido a mudanças na legislação.  Atualizar toda a aplicação não era uma opção a ser considerada, então decidi implementar uma funcionalidade que permitisse que a aplicação fizesse o download de trechos de código que eram alterados frequentemente e substituisse o trecho antigo, passando a utilizar o novo algoritmo.

A aplicação em questão realiza alguns cálculos de taxas que mudam mensalmente. Agora o aplicativo busca no servidor o código a ser utilizado para realizar os cálculos de forma dinâmica.

Para fazer isto utilizei a class CSharpCodeProvider do framework Dotnet, que permite que usemos código em C# como uma linguagem script.

Neste artigo mostro como criar uma aplicação simples que possui dois listbox, o primeiro possui uma relação de países, e o segundo será populado através de um código que deve ser informado pelo proprio usuario em um textbox..

Classe de apoio para instanciação do trecho de codigo

using Microsoft.CSharp;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;

namespace WindowsFormsApplication1
{
    public class CodeHelper
    {
        public static object HelperFunction(String classCode, String mainClass, Object[] requiredAssemblies)
        {
            CSharpCodeProvider provider = new CSharpCodeProvider(new Dictionary<string, string> 
              { 
                 { "CompilerVersion", "v4.0" } 
              });

            CompilerParameters parameters = new CompilerParameters
            {
                GenerateExecutable = false,       // Create a dll
                GenerateInMemory = true,          // Create it in memory
                WarningLevel = 3,                 // Default warning level
                CompilerOptions = "/optimize",    // Optimize code
                TreatWarningsAsErrors = false     // Better be false to avoid break in warnings
            };

            //----------------
            // Add basic referenced assemblies
            parameters.ReferencedAssemblies.Add("system.dll");
            parameters.ReferencedAssemblies.Add("System.Windows.Forms.dll");
            parameters.ReferencedAssemblies.Add("System.Core.dll");

            //----------------
            // Add all extra assemblies required
            foreach (var extraAsm in requiredAssemblies)
            {
                parameters.ReferencedAssemblies.Add(extraAsm as string);
            }

            //--------------------
            // Try to compile the code received
            CompilerResults results = provider.CompileAssemblyFromSource(parameters, classCode);

            //--------------------
            // If the compilation returned error, then return the CompilerErrorCollection class 
            // with the errors to the caller
            if (results.Errors.Count != 0)
            {
                return results.Errors;
            }

            //--------------------
            // Return the created class instance to caller
            return results.CompiledAssembly.CreateInstance(mainClass); ;
        }
    }
}

Esta clkasse é apenas um “helper” para facilitar a instanciação do script informado. Basta passar o codigo para esta classe em conjunto com o nome da classe principal do código que está sendo enviado e caso necessário os assemblies utilizados.

Form principal

No form principal, In existe um textbox chamado txtCodeToRun. Neste textbox o usuario poderá informar o código que será utilizado para ler o primeiro listbox e popular o segundo listbox. Neste exemplo, voce não precisa criar a função nem definir a classe, pois isto já estará pré-definido. Basta informar o conteúdo da função. Perceba que pego o trecho de codigo informado e já concateno com a classe e a definição da função. Obviamente voce poderia permitir que toda a definição da classe fosse informada e executada.

Segue o código do form:

using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnRunCode_Click(object sender, EventArgs e)
        {
            Execute(txtCodeToRun.Text);
        }

        private void Execute(string code)
        {
            StringBuilder sb = new StringBuilder();

            //-----------------
            // Create the class as usual
            sb.AppendLine("using System;");
            sb.AppendLine("using System.Windows.Forms;");
            sb.AppendLine("using System.Collections.Generic;");
            sb.AppendLine();
            sb.AppendLine("namespace CountryList");
            sb.AppendLine("{");

            sb.AppendLine("      public class SelectCountries");
            sb.AppendLine("      {");

            // My pre-defined class named FilterCountries that receive the sourceListBox
            sb.AppendLine("            public List<string> FilterCountries(ListBox countryList)");
            sb.AppendLine("            {");
            sb.AppendLine(code);
            sb.AppendLine("            }");
            sb.AppendLine("      }");
            sb.AppendLine("}");

            //-----------------
            // The finished code
            String classCode = sb.ToString();

            //-----------------
            // Dont need any extra assemblies
            Object[] requiredAssemblies = new Object[] { };

            dynamic classRef;
            try
            {
                txtErrors.Clear();

                //------------
                // Pass the class code, the namespace of the class and the list of extra assemblies needed
                classRef = CodeHelper.HelperFunction(classCode, "CountryList.SelectCountries", requiredAssemblies);
                
                //-------------------
                // If the compilation process returned an error, then show to the user all errors
                if (classRef is CompilerErrorCollection)
                {
                    StringBuilder sberror = new StringBuilder();

                    foreach (CompilerError error in (CompilerErrorCollection) classRef)
                    {
                        sberror.AppendLine(string.Format("{0}:{1} {2} {3}", 
                                           error.Line, error.Column, error.ErrorNumber, error.ErrorText));
                    }

                    txtErrors.Text = sberror.ToString();
                    
                    return;
                }
            }
            catch (Exception ex)
            {
                // If something very bad happened then throw it
                MessageBox.Show(ex.Message);
                throw;
            }

            //-------------
            // Finally call the class to filter the countries with the specific routine provided
            List<string> targetValues = classRef.FilterCountries(lstSource);

            //-------------
            // Move the result to the target listbox
            lstTarget.Items.Clear();
            lstTarget.Items.AddRange(targetValues.ToArray());
        }
    }
}

Como voce pode verificar, o textbox irá conter o corpo da função, e a funcao irá receber como único parâmetro o listbox que contem a lista de países. De posse desta informação, dentro da função voce irá popular a variavel de retorno (um List<string>) que posteriormente será utilizado para popular o segundo listbox. Outro enfoque possivel seria passar os dois listbox como parametro e a operação seria realizada diretamente no listbox de destino.

Dentro da função voce pode realizar qualquer operacao no listbox de origem que desejar, iremos aqui apenas selecionar alguns dos elementos e popular a variavel de retoro irá popular o listbox de destino.

Se o script digitado apresentar algum erro, a classe “helper” irá retornar o erro, e neste exemplo iremos mostrar os erros na parte de baixo da tela.

Use o seguinte trrecho de código para adicionar no listbox de destino todos os países que iniciam com a letra “C”:

List<string> result = new List<string>();

foreach (string country in countryList.Items)
{
    if (country.StartsWith("C", StringComparison.InvariantCultureIgnoreCase))
    {
        result.Add(country);
    }
}

return result;

Dynamic Code Example

Assim, outro exemplo seria popular a lista com os paises que iniciam com “C” e “G”:

List<string> result = new List<string>();

foreach (string country in countryList.Items)
{
    if (country.StartsWith("C", StringComparison.InvariantCultureIgnoreCase) ||
        country.StartsWith("G", StringComparison.InvariantCultureIgnoreCase))
    {
        result.Add(country);
    }
}

return result;

É isto. Bem simples e uma funcionalidade extremamente interessante que pode trazer diversos benefícios para sua aplicação.

Voce pode fazer o download do código fonte em Here (ZIP file)

]]>
http://ptbr.oleonardomachado.com/2015/02/10/executando-codigo-dinamicamente-em-net-compilando-codigo-c-em-runtime/feed/ 0
Polymer: Criando um novo componente de lista – Parte 2 http://ptbr.oleonardomachado.com/2015/01/20/polymer-criando-um-novo-componente-de-lista-parte-2/ http://ptbr.oleonardomachado.com/2015/01/20/polymer-criando-um-novo-componente-de-lista-parte-2/#comments Tue, 20 Jan 2015 22:26:08 +0000 http://ptbr.oleonardomachado.com/?p=93 Agora que já expliquei como fazer um novo componente, vou otimizá-lo e adicionar um visual mais agradável..

Alterações ao componente the listcard-person

Alterei o componente listcard-person tornando-o mais eficiente. Primeiramente, removi a utilização do componente core-list e agora estou utilizando a própria tag template utilizando o atributo repeat.

Anteriormente

<div fit style=" padding-top: 70px">
  <core-list id="list" data="{{personData}}" style="height:100%;" >
    <template>
      <div style='padding-bottom: 20px;'>
      <div>
         <b>Name:</b> <span>{{model.name}}</span>
      </div>
      <div>
         <b>Address:</b> <span>{{model.address}}</span>
      </div>
      <div>
         <b>Profession:</b> <span>{{model.profession}}</span>
      </div>
      </div>
    </template>
  </core-list>
</div>

Nova versão

<div style='margin-bottom: 30px' layout vertical center-center>
  <template repeat="{{person in personData}}">
    <div class="card" layout vertical>
      <h2>{{person.name}}</h2>
      <div style="text-align: left;">
        <div class="label">Address</div>
        <div>{{person.address}}</div>
      </div>
      <div style="text-align: left;">
        <div class="label">Name</div>
        <div>{{person.profession}}</div>
      </div>
    </div>
    <div>&nbsp;</div>
  </template>
</div>

Usando a funcionalidade de repeat do <template> foi possivel reduzir a complexidade, haja vista que o componente core-list é muito robusto para a simplicidade que o exemplo apresenta. Repeat é utilizado para fazer o bind de uma coleção ao conteúdo do template. Neste exemplo, irei trabalhar com a coleção personData e cada elemento desta coleção será atribuido à variável “person” para cada item da coleção.

Dentro do template utilizamos a variável “person” a fim de acessar os dados de cada elemento (i.e. person.name, person.address and person.profession).

Algumas mudanças foram realizadas no estilo do componente e estão disponíveis no download abaixo.

Alterações em Index.html

O arquivo index.html foi alterado a fim de melhorar o visual, removendo alguns componentes e adicionando outros.

Agora os componentes em uso são:

<link rel="import" href="bower_components/core-scaffold/core-scaffold.html">
<link rel="import" href="bower_components/core-header-panel/core-header-panel.html">
<link rel="import" href="listcard-person.html">

Utilizei um css especialmente preparado para ser utilizado com o Polymer. Este css pode ser baixado de PolymerTemplates onde voce encontrará diversos outros templates css gratuitos. Utilizei o template The Times neste exemplo.

<link rel="stylesheet" type="text/css" href="css/the-times.css">

O conteudo completo de index.html foi alterado, entretanto a seção do script continua a mesma do componente mostrado na parte 1 deste artigo.

<body unresolved>
  <core-header-panel>
    <core-toolbar>Sample Application</core-toolbar>
  </core-header-panel>

  <div id="container">
    <section hero>
      <listcard-person show="contacts" id="personlist" />
    </section>
  </div>

<script>
  document.addEventListener('polymer-ready', function() {
    var obj = document.querySelector('#personlist');
    var data = [{
      "name": "Another User 5",
      "address": "Av. 5 St. CD",
      "profession": "Profession Another user 5"
    }, {
      "name": "Another User 6",
      "address": "Av. 6 St. BD",
      "profession": "Profession Another user 6"
    }, {
      "name": "Another User 7",
      "address": "Av. 7 St. CA",
      "profession": "Profession Another user 7"
    }, {
      "name": "Another User 8",
      "address": "Av. 8 St. DA",
      "profession": "Profession Another user 8"
    }, {
      "name": "Another User 9",
      "address": "Av. 12 St. CA",
      "profession": "Profession Another user 9"
    }, {
      "name": "Another User 10",
      "address": "Av. 13 St. CA",
      "profession": "Profession Another user 10"
    }, {
      "name": "Another User 11",
      "address": "Av. 11 St. CA",
      "profession": "Profession Another user 11"
    }, ]
    obj.loadData(data);
  });
  </script>

</body>

Você pode verificar o resultado na imagem abaixo. Você perceberá que optei por apresentar uma aparência similar ao material design.

ImgSample1

 

Voce pode fazer o download dos arquivos deste projeto no link a seguir. O download não inclui os componentes nativos do Polymer que devem ser baixados/instalados utilizando o bower (como mostrado no artigo Polymer: Basic installation).

Faça o download RAR file ou ZIP file.

Na próxima parte deste artigo irei mostrar como inserir dados na lista utilizando os componentes do Polymer.

]]>
http://ptbr.oleonardomachado.com/2015/01/20/polymer-criando-um-novo-componente-de-lista-parte-2/feed/ 0
Componente: Card Library http://ptbr.oleonardomachado.com/2015/01/05/componente-card-library/ http://ptbr.oleonardomachado.com/2015/01/05/componente-card-library/#comments Mon, 05 Jan 2015 15:30:28 +0000 http://ptbr.oleonardomachado.com/?p=88 O componente Card Library permite, de uma forma bem simples, utilizar a interface oficial do google CardView em sua aplicação Android.

É uma biblioteca muito boa que pode melhorar significativamente a interface de seu app permitindo a criação de views muito atraentes.

Pode ser utilizada a partir da versão 14 (4.0) da API. Infelizmente não pude utilizá-la em minha App porque tenho que suportar a partir da versão 10 (2.3.3) da API, entretanto em uma nova App com certeza irei utilizá-la.

Encontrei a Card Library no github em Card Library (Copyright Gabriele Mariotti).

Voce pode fazer o download de um aplicativo de demonstração em  CardsLib Demo

 

CardsLib

(imagem retirada do site do autor no githug)
]]>
http://ptbr.oleonardomachado.com/2015/01/05/componente-card-library/feed/ 0
Polymer: Criando um novo componente de lista http://ptbr.oleonardomachado.com/2014/12/25/polymer-criando-um-novo-componente-de-lista/ http://ptbr.oleonardomachado.com/2014/12/25/polymer-criando-um-novo-componente-de-lista/#comments Fri, 26 Dec 2014 00:55:47 +0000 http://ptbr.oleonardomachado.com/?p=80 Trecho extraído do website do Google Polymer:

Polymer é uma biblioteca pioneira que torna mais fácil e simples do que nunca a construção de aplicações bonitas na web. Polymer foi construído com base em um conjunto de novas primitivas para plataforma web conhecidas como Web Components. Web Components permitem um nível de interoperabilidade e composição para a nova plataforma web. O resultado é um aumento considerável na produtividade do desenvolvedor.

O conceito principal no Polymer é dar ao desenvolvedor a oportunidade de criar novas aplicações baseadas em componentes web. Desta forma, após o desenvolvimento de componentes, diversas aplicações podem ser desenvolvidas utilizando-se estes pequenos pedaços de funcionalidade que possuem, além do layout, código próprio. Você pode utilizar os mesmos componentes inúmeras vezes na mesma página, aplicativo ou até em aplicativos diferentes.

Polymer ainda está em desenvolvimento, porém está em uma versão bem estável, sendo que diversos pequenos já estão utilizando a biblioteca. Este pequeno tutorial utilizou a versão 0.5.1 do Polymer.

Neste artigo irei mostrar como construir um componente bem simples, que irá receber um object (ou uma string JSON) com dados de algumas pessoas e irá renderizar a lista destas pessoas.

Importante !
Se voce ainda não conhece o Polymer, sugiro que leia este artigo primeiro Polymer: Instalação Básica. Assim você poderá instalar todas as ferramentas necessárias para utilizar o Polymer.

Existe muita informação sobre o Polymer em Polymer website

Seu trabalho com o Polymer ficará muito mais simples caso opte por instalar as ferramentas sugeridas.

Na primeira parte deste tutorial irei construir um novo componente que irá mostrar uma lista de pessoas. Depois, em um segundo artigo, irei fazer algumas alterações para melhorar a aparência e utilizar outros componentes já disponibilizados pela própria biblioteca.

Construindo o novo componente (Element)

Para este argito irei criar um novo componente a fim de mostrar informações sobre algumas pessoas (nome, endereço e profissão). Sendo assim, crie primeiro um arquivo chamado  listcard-person.html com o template básico para o novo componente.

<polymer-element name="listcard-person" layout vertical>
  <template>
  </template>
  <script>
    Polymer('listcard-person', {
    });
  </script>
</polymer-element>

Como voce pode ver dei ao componente o nome de listcard-person na tag html e também no script de criação.

Crie também um arquivo index.html que irá utilizar o listcard-person.html. A pagina html básica, sem informações sobre o Polymer:

<!doctype html>
<html>
  <head>
    <title>Listcard-person sample</title>
  </head>
<body fit>
</body>
</html>

Adicione os links que serão necessários. O link para webcomponents.js, é a parte principal do Polymer.

<script src="bower_components/webcomponentsjs/webcomponents.js"></script>
<link rel="import" href="bower_components/core-list/core-list.html">

Iremos utilizar outro componente da biblioteca do Polymer chamada core-list, porque nosso componente precisa dele para fazer a renderização da lista. Então primeiro precisamos instalar as dependências primeiro, e faremos isso utilizando o Bower (verifique Polymer: Instalação Básica para mais informações sobre o Bower).

bower install Polymer/core-list

Finalmente adicione o link para o novo componente

<link rel="import" href="listcard-person.html">

Adicione o componente ao corpo do ndex.html, e dê a ele um id

<listcard-person id="personlist" />

Neste momento o index.html se aparenta com isso:

<!doctype html>
<html>
  <head>
    <title>Address Element</title>
    <script src="bower_components/webcomponentsjs/webcomponents.js"></script>
    <link rel="import" href="bower_components/core-list/core-list.html">
    <link rel="import" href="listcard-person.html">
  </head>
<body fit>
  <listcard-person id="personlist" />
</body>
</html>

Retornando ao nosso listcard-person.html, dentro da tag <template> iremos adicionar o layout para nosso componente. Você pode usar qualquer tag html que desejar. Como iremos mostrar uma lista com informações de diversas pessoas, precisamos utilizar um componente chamado <core-list>. Este componente da própria biblioteca é o ponto de partida para desenvolver a carga dos dados a partir da nossa fonte de dados. Nosso plano é passar um string JSON ou um objeto para nosso componente com a informações de diversas pessoas e repassar ao componente  <core-list> para que ele varra cada item e renderize a informação.

<link rel="import" href="bower_components/polymer/polymer.html">

<polymer-element name="listcard-person" layout vertical>
  <template>
    <h2>Address List</h2>
    <div fit style=" padding-top: 70px">
      <core-list id="list" data="{{personData}}" style="height:100%;" >
        <template>
          <div style='padding-bottom: 20px;'>
            <div>
              <b>Name:</b> <span>{{model.name}}</span>
            </div>
            <div>
              <b>Address:</b> <span>{{model.address}}</span>
            </div>
            <div>
              <b>Profession:</b> <span>{{model.profession}}</span>
            </div>
          </div>
        </template>
      </core-list>
    </div>
  </template>
  <script>
    Polymer('listcard-person', {
    });
  </script>
</polymer-element>

No elemento <core-list> você pode verificar que adicionei um atributo chamado data com o valor de {{personData}}. Este personData é a nossa fonte de dados. Iremos popular através do javascript uma variável chamada personData com os dados das pessoas que iremos listar.
Dentro da tag template de <core-list> nós iremos fazer o layout a ser utilizado na renderização dos dados de cada pessoa, e fazer o bind dos dados da variável para o html. Dentro de core-list nós temos acesso à variável datasource através de uma outra variável chamada model que aponta para cada elemento do nosso datasource. Este nosso datasource tem esse formato:

dataSource = [ 
               {  "name": "User 1", 
                  "address":"Address of User 1", 
                  "profession":"Profession of user 1"}, 
               {  "name": "User 2", 
                  "address":"Address of User 2", 
                  "profession":"Profession of user 1"}, 
             ]

Sendo assim usamos model.name para recuperar o nome, model.address para recuperar o endereço e assim por diante.

Agora devemos receber os dados e fazer a associação do bind. Irei mostrar duas formas que faremos isso.

Populando a lista utilizando atributos

Para passar dados para um componente podemos utilizar a passagem  de dados  através de tags html para valores estáticos. Altere index.html

<listcard-person id="personlist"/>

para

<listcard-person id="personlist" initialData='[
  {"name": "User 1", 
      "address":"Av. 1 St. A", 
      "profession":"Profession user 1"}, 
  {"name": "User 2", 
      "address":"Av. 2 St. B", 
      "profession":"Profession user 2"}, 
  {"name": "User 3", 
      "address":"Av. 3 St. C", 
      "profession":"Profession user 3"}, 
  {"name": "User 4", 
      "address":"Av. 4 St. D", 
      "profession":"Profession user 4"} ]' />

Como você pode ver, utilizei um novo atributo chamado initialData para passar um string JSON para o novo componente e em listcard-person.html precisamos agora receber o valor.

Altere a primeira linha onde definimos o elemento de

<polymer-element name="listcard-person" layout vertical>

para

<polymer-element name="listcard-person" layout vertical attributes="initialData">

Isto informa ao componente que esperamos receber um atributo chamado initialData

Agora a alteração do script. Quando o componente estiver pronto (quando tudo já tiver sido carregado), iremos verificar se quem chamou o componente passou alguma informação no atributo initialData. Caso possua algum valor, iremos converter de JSON para um objeto e utilizar ele para fazer o bind das informações através de personData (nosso datasource no atributo “data” do  <core-list>).

<script>
  Polymer('listcard-person', {
    ready: function() {
      if (this.attributes.hasOwnProperty("initialData")) {
        this.personData = JSON.parse(this.attributes['initialData'].value);
      }
    }
  });
</script>

Agora você já pode salvar todas as alterações e recarregar a página para ver a funcionalidade. Você irá ver uma lista bem simples com todos os valores.

Populando a lista utilizando javascript

A segunda forma que iremos implementar para popular o componente é através de uma chamada javascript.

Em listcard-person.html, adicione uma função javascript chamada loadData que irá receber um objeto e associá-lo ao datasource de <core-list>.

<script>
  Polymer('listcard-person', {
    ready: function() {
      if (this.attributes.hasOwnProperty("initialData")) {
        this.personData = JSON.parse(this.attributes['initialData'].value);
      }
    },
    loadData: function(dt) {
       this.personData = dt;
    }
  });
</script>

Faça outra alteração em index.html para chamar nossa nova função a fim de popular o datasource.

Altere a definição de nosso componente em index.html novamente de

<listcard-person 
       id="personlist" 
       initialData='[{"name": "User 1", 
                          "address":"Av. 1 St. A", 
                          "profession":"Profession user 1"}, 
                     {"name": "User 2", 
                          "address":"Av. 2 St. B", 
                          "profession":"Profession user 2"}, 
                     {"name": "User 3", 
                          "address":"Av. 3 St. C", 
                          "profession":"Profession user 3"}, 
                     {"name": "User 4", 
                          "address":"Av. 4 St. D", 
                          "profession":"Profession user 4"} ]' />

para

<listcard-person id="personlist"/>

Adicione o script abaixo ao arquivo index.html. O que fiz foi adicionar um listener ao evento “polymer-ready“, que irá ser chamado quanto o Polymer estiver pronto para iniciar (todas as dependências já foram baixadas).
Neste momento, iremos localizar nosso componente (demos a ele o nome de personlist), criaremos um novo objeto com os valores que desejamos popular o componente e chamaremos a função loadData que implementamos no componente.

<script>
  document.addEventListener('polymer-ready', function() { 
    var obj = document.querySelector('#personlist');
    var data = [
                 {"name": "Another User 5", 
                      "address":"Av. 5 St. CD", 
                      "profession":"Profession Another user 5"}, 
                 {"name": "Another User 6", 
                      "address":"Av. 6 St. BD", 
                      "profession":"Profession Another user 6"}, 
                 {"name": "Another User 7", 
                      "address":"Av. 7 St. CA", 
                      "profession":"Profession Another user 7"}, 
                 {"name": "Another User 8", 
                      "address":"Av. 8 St. DA", 
                      "profession":"Profession Another user 8"},
                 {"name": "Another User 9", 
                      "address":"Av. 12 St. CA", 
                      "profession":"Profession Another user 9"}, 
                 {"name": "Another User 10", 
                      "address":"Av. 13 St. CA", 
                      "profession":"Profession Another user 10"}, 
                 {"name": "Another User 11", 
                      "address":"Av. 11 St. CA", 
                      "profession":"Profession Another user 11"}, 
               ]
    obj.loadData(data);
  });
</script>

Quando você carregar a pagina agora os dados serão mostrados através desta chamada a loadData().

No próximo artigo ire mostrar como fazer um layout mais agradável e bem trabalhado com outras funcionalidades da biblioteca do Polymer.

]]>
http://ptbr.oleonardomachado.com/2014/12/25/polymer-criando-um-novo-componente-de-lista/feed/ 0
Polymer: Instalação Básica http://ptbr.oleonardomachado.com/2014/12/24/polymer-instalacao-basica/ http://ptbr.oleonardomachado.com/2014/12/24/polymer-instalacao-basica/#comments Wed, 24 Dec 2014 16:33:51 +0000 http://ptbr.oleonardomachado.com/?p=77 Existe um guia detalhado sobre a instalação do Polymer em  Installing Polymer.

Aqui apresento um pequeno guia, sem detalhamento. Caso você precise de maiores detalhes, verifique o site oficial.

Para montar o ambiente para desenvolver você vai precisar de:

  • Bower – Para resolver as dependências e baixar os pacotes necessários
  • NodeJS and npm – Exigido pelo Bower
  • Git – Exigido pelo Bower

Instalação do NodeJs e npm

Vá no site do projeto NodeJS and npm , faça o download e instale o NodeJs.

Instalação do Git

Vá no site do projeto git, faça o download e instale o Git.

Instalação do Bower

Para instalar o Bower, abre o prompt de comando e execute

c:\npm install -g bower

Criação de um novo projeto Polymer

Agora que todas as ferramentas já estão instaladas, você pode criar um novo projeto e fazer o download dos componentes do Polymer.

Crie um novo folder e use-o para armazenar seu projeto. Por exemplo, crie um novo folder chamado polsample in c:

cd\
mkdir polsample
cd polsample

Agora inicialize o setup do projeto através do Bower

c:\polsample\bower init

Responda as perguntas. Apos finalizar, um novo arquivo chamado bower.json vai ser criado em c:\polsample\.

Instale o Polymer:

c:\polsample\bower install --save Polymer/polymer

O Bower cria um novo folder chamado bower_components dentro do folter polsample (c:\polsample\bower_components) e adiciona a nova dependência dentro do seu bower.json. Neste momento o arquivo deve estar parecido com este:

{
  "name": "polsample",
  "version": "1.0.0",
  "dependencies": {
    "polymer": "Polymer/polymer#~0.5.1"
  }
}

Se você precisar atualizar as dependências, execute:

c:\polsample\bower update

Instalação de componentes do Polymer

QUando voce precisar utilizar um componente do Polymer, basta fazer a instalação através do Bower. Por exemplo, caso voce crie um projeto e deseje utilizar o componente paper-button, você deve rodar o comando

c:\polsample\bower install Polymer/paper-button

E posteriormente adicionar o link deste componente na pagina de seu projeto.:

<link rel="import" href="bower_components/paper-button/paper-button.html">

Você pode encontrar informações sobre os nomes dos componentes no site do projeto Polymer. Para papper-button a página é paper-button

É só isso. Em outro artigo irei mostrar como criar um componente personalizado.

]]>
http://ptbr.oleonardomachado.com/2014/12/24/polymer-instalacao-basica/feed/ 0
Localização – Como traduzir um aplicativo Android http://ptbr.oleonardomachado.com/2014/12/18/localizacao-como-traduzir-um-aplicativo-android/ http://ptbr.oleonardomachado.com/2014/12/18/localizacao-como-traduzir-um-aplicativo-android/#comments Fri, 19 Dec 2014 00:07:43 +0000 http://ptbr.oleonardomachado.com/?p=18 A tarefa de implementar a tradução de um aplicativo Android é bem simples de ser implementada, bastando criar os arquivos de recursos para cada língua a ser utilizada, e posteriormente o próprio Android se encarrega de apresentar a tradução correta.

Este artigo cobre o processo de criar os arquivos de recursos e a forma de se forçar a apresentação em um determinado idioma caso desejado. Preparei o exemplo com três idiomas, ingles, espanhol e português. Todos os passos apresentados foram realizados utilizando-se o Android Studio.

Ao iniciar um novo projeto no Android Studio, voce terá uma estrutura como esta ao lado, contendo um diretório /res/values  e dentro dele um arquivo strings.xml. Neste arquivo voce deve colocar todos os textos a serem utilizados em seus layouts de forma que eles fiquem centralizados em um único ponto, facilitando a tradução e organização.
localization_1

 

Crie dentro do diretório /res, uma pasta chamada values-en e dentro dela crie um arquivo chamado strings.xml. Depois crie outra pasta dentro do diretório /res chamada values-es e dentro desta crie um arquivo chamado strings.xml, de forma a ter uma estrutura como a da figura ao lado.

localization_2

 

O arquivo /values/strings.xml deverá conter os os textos no idioma padrão do app (em nosso caso o português)

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <string name="app_name">Demonstracao</string>
 <string name="ola_mundo">Olá mundo!</string>
 <string name="action_settings">Settings</string>
</resources>

Edite o arquivo de /values-es/strings.xml e insira a tradução para espanhol

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <string name="ola_mundo">Hola Mundo!!</string>
</resources>

E finalmente edite o arquivo de /values-en/strings.xml e coloque a tradução para inglês

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <string name="ola_mundo">Hello world!</string>
</resources>

O Android Studio possui uma ferramenta para ajudar na tradução dos textos. Para usá-la clique com o botao direito do mouse sobre qualquer um dos arquivos strings.xml e selecione a opção Open Translation Editor

localization_3

 

E uma tela como essa irá aparecer mostrando cada texto e a atual tradução para cada um. Neste ponto basta cadastrar as traduções para cada idioma. Esta funcionalidade é extremamente útil na medida em que permite visualizar em um único local todas as traduções para cada chave.

localization_4

Agora vamos fazer uma activity para mostrar um TextView contendo o valor da chave “ola_mundo”.

O Android Studio já criou um layout chamado activity_main.xml. Ajuste o conteúdo dele para:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" 
    tools:context=".MainActivity">

    <TextView android:text="@string/ola_mundo" 
         android:textSize="43sp"
         android:layout_width="wrap_content" 
         android:layout_height="wrap_content" />

</RelativeLayout>

E criou também a classe correspondente.

package com.test.demo;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

Desta forma, caso seu dispositivo esteja configurado para o idioma inglês, este resultado será apresentado:

localization_5

Ou, caso esteja configurado para o idioma espanhol esta tela será apresentada:

localization_6

Desta forma, dependendo de qual seja a configuração do usuário o idioma correspondente será utilizado. Caso não exista uma tradução específica para o idioma do usuário, o idioma padrão será utilizado. Em nosso caso, por exemplo caso o usuário tenha como idioma o francês, não estamos propiciando uma tradução para esta língua, então a tradução existente no folder /res/values  (neste caso o português) será utilizado para fornecer os textos.

Além disso, você também pode disponibilizar dentro de sua aplicação a funcionalidade de deixar o usuário escolher o idioma desejado, permitindo que, mesmo estando em outra configuração, o aplicativo seja apresentado em outro idioma. Isso pode ser feito através desta pequena função que irá alterar o idioma de seu app:

public void setLocale(String lang) {
        Locale myLocale = new Locale(lang);
        Resources res = getResources();
        DisplayMetrics dm = res.getDisplayMetrics();
        Configuration conf = res.getConfiguration();
        conf.locale = myLocale;
        res.updateConfiguration(conf, dm);
        Intent refresh = new Intent(this, MainActivity.class);
        refresh.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(refresh);
}

E para chamá-lo basta passar o idioma desejado

setLocale("es");

Lembre-se que essa alteração não é definitiva, ou seja, ao sair do App e entrar novamente, o idioma do dispositivo voltará a ser utilizado. Sendo assim, caso queira manter sempre o idioma selecionado pelo usuário, você terá que armazenar a preferência de idioma dele e sempre que iniciar o App chamar a função acima.

Para testar em um emulador, você pode alterar o idioma deste da seguinte forma:

Passo 1
Inicie o emulador
Passo 2
Execute

adb shell

ou

adb -e shell caso tenha também conectado um dispositivo

Passo 3
Quando o prompt aparecer execute o comando

setprop persist.sys.language [langcode];setprop persist.sys.country [ccode];stop;sleep 5;start

substituindo o [langcode] pelo código do idioma e o [ccode] pelo código do pais

ex.

setprop persist.sys.language es;setprop persist.sys.country ES;stop;sleep 5;start

que mudará o idioma para espanhol e o pais para Espanha

 

]]>
http://ptbr.oleonardomachado.com/2014/12/18/localizacao-como-traduzir-um-aplicativo-android/feed/ 0
Biblioteca: Butter Knife http://ptbr.oleonardomachado.com/2014/12/17/biblioteca-butter-knife/ http://ptbr.oleonardomachado.com/2014/12/17/biblioteca-butter-knife/#comments Thu, 18 Dec 2014 00:56:25 +0000 http://ptbr.oleonardomachado.com/?p=16 Após desenvolver a primeira versão do meu app, encontrei a Butter Knife (Copyright 2013 Jake Wharton) que é uma biblioteca muito útil.

O objetivo principal dela é simplificar o processo de “inflate” das views e associações dos componentes de tela com as variáveis do programa, permitindo que voce se preocupe com o código que realmente faz parte da sua aplicação e não com código de gerenciamento de telas. Com o Butter Knife voce faz anotações em suas views e controles permitindo que a propria biblioteca faça o processo de “inflate” e de obtenção dos ponteiros para os controles da interface.

Sendo assim, ao invés de ter este código:

class ClientActivity extends Activity {
  TextView name;
  TextView phone;

  @Override public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.client_activity);
	
	name = (EditText) view.findViewById(R.id.name);
	phone = (EditText) view.findViewById(R.id.phone);
  }
}

Voce teria algo semelhante a isso:

class ClientActivity extends Activity {
  @InjectView(R.id.name) TextView name;
  @InjectView(R.id.phone) TextView phone;

  @Override public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.client_activity);
    
	ButterKnife.inject(this);
  }
}

Diversas outras funcionalidades estão disponíveis na biblioteca, como a injeção opcional (para situações em que o controle pode ou não estar na tela)

// The age control may or may not exists in the view
@Optional @InjectView(R.id.age) TextView age;

// If the field age exists, them assign an onClick event to it
@Optional @OnClick(R.id.age) void onAgeClicked() {
  // TODO ...
}

Além disso voce pode associar automaticamente eventos para os controles:

@OnClick(R.id.submit)
public void submit(View view) {
  // TODO submit data to server...
}

Voce pode encontrar informações mais detalhadas das funcionalidades da biblioteca bem como instruções para instalação em developer website.

Outra ferramenta muito útil é Android ButterKnife Zelezny que voce pode adicionar ao Android Studio como um plugin e tornar automatico a geração do código para a injeção dos dados.

]]>
http://ptbr.oleonardomachado.com/2014/12/17/biblioteca-butter-knife/feed/ 0
Componente: Calendar http://ptbr.oleonardomachado.com/2014/12/17/componente-calendar/ http://ptbr.oleonardomachado.com/2014/12/17/componente-calendar/#comments Thu, 18 Dec 2014 00:47:34 +0000 http://ptbr.oleonardomachado.com/?p=11 O Roboto Calendar View é um bom componente que provê um calendário razoavelmente customizável para uso geral. Em meu app preciso mostrar um calendário onde marco os dias em que existem compromissos. Uma funcionalidade bem simples atualmente.

Eu encontrei o Roboto Calendar View no github em RobotoCalendarView (Copyright 2014 Marco Hernaiz Cao).

Este componente possui algumas fontes interessantes para usar nos projetos (que entretanto removi para reduzir o tamanho do meu APK) que voce pode usar para alterar a interface de acordo com suas necessidades.

Voce pode encontrar mais informações sobre a utilização na própria página do projeto no github.

Em um futuro próximo irei precisar melhorar o componente ou encontrar outro que possua informações mais detalhadas para o usuário, entretanto por hora o atual me serve.

AdvogadoAG - RobotoCalendarView

]]>
http://ptbr.oleonardomachado.com/2014/12/17/componente-calendar/feed/ 0
Olá http://ptbr.oleonardomachado.com/2014/11/21/hello-world/ http://ptbr.oleonardomachado.com/2014/11/21/hello-world/#comments Fri, 21 Nov 2014 04:51:49 +0000 http://localhost/wordpress-4.0.1/wordpress/?p=1 Olá, sou Leonardo Machado, desenvolvedor do aplicativo AdvogadoAg uma agenda para advogados. A princípio criei este aplicativo apenas para android, porém agora iniciei a conversão para Windows Phone e em breve para iOS (Swift). Minha inteção é abordar temas interessantes de desenvolvimento para estes ambientes bem como descreve os percalços encontrados na conversão do aplicativo para as outras plataformas.

]]>
http://ptbr.oleonardomachado.com/2014/11/21/hello-world/feed/ 0