Generation App – Día 10 – Trabajar con mosaicos en Windows Phone

Cuando vemos la pantalla de inicio de Windows Phone, todo lo que vemos son Tiles, o mosaicos; y en cada mosaico (o la mayoría), nos muestra información de nuestro interés, sin ninguna necesidad de abrir la aplicación, como es el caso del mosaico de correos electrónicos y mensajería, que sin necesidad de entrar a estas aplicaciones, podemos enterarnos si hemos recibido un correo o un mensaje simplemente viendo el mosaico correspondiente.

Ha llegado el momento que aprendas a desarrollar esta súper útil funcionalidad. En este ejemplo vas a implementar un nuevo proyecto con tres paginas que se muestran a continuación: MainPage, ApplicationTile y SecondaryTile

Creando el proyecto y Layout de la Interfaz

  1. Crea un nuevo proyecto Silverlight For Windows Phone y nómbraloTileSample

  2. Utiliza Microsoft Paint o cualquier otro programa de editor de imágenes para crear tres archivos de imágenes de mosaico de 173 x 173 pixeles usados como imágenes de fondo. Nómbralos “Red.jpg”, “Blue.jpg” y “Green.jpg”. Puedes descargarte el proyecto de ejemplo y utilizas las imágenes que este utiliza. Agrega estas tres imágenes a tu proyecto haciendo clic derecho al proyecto, y selecciona Add -> Existing Item. Selecciona las tres imágenes y da clic en Add. Para cada imagen, selecciona la propiedad Build Action a tipo Content.

  3. Establece el nombre de la aplicación y el titulo de la pagina reemplazando elTitlePanelcon el siguiente código XAML.

    <!--TitlePanel contains the name of the application and page title-->
    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
        <TextBlock x:Name="ApplicationTitle" Text="Tile Sample" Style="{StaticResource PhoneTextNormalStyle}"/>
        <TextBlock x:Name="PageTitle" Text="Tiles" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
    </StackPanel>
  4. El código del MainPage se encuentra mas abajo. Contiene un text block y dos botones:

    Cada botón tendrá un manejador de evento clic. Para crear la IU de MainPage, reemplaza <Grid x:Name=”ContentPanel” Grid.Row=”1″ Margin=”12,0,12,0″></Grid> de MainPage.xaml con el siguiente código:

    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <TextBlock Height="170" HorizontalAlignment="Left" Margin="12,6,0,0" Name="textBlockDescription" Text="This sample demonstrates how to update Application Tiles.  It also demonstrates how to create, update, and delete secondary Tiles." VerticalAlignment="Top" Width="438" TextWrapping="Wrap" TextAlignment="Left" />
        <Button Content="Change Application Tile" Height="72" HorizontalAlignment="Left" Margin="28,182,0,0" Name="buttonChangeApplicationTile" VerticalAlignment="Top" Width="392" Click="buttonChangeApplicationTile_Click" />
        <Button Content="Change Secondary Tile" Height="72" HorizontalAlignment="Left" Margin="28,278,0,0" Name="buttonChangeSecondaryTile" VerticalAlignment="Top" Width="392" Click="buttonChangeSecondaryTile_Click" />
    </Grid>
  5. El siguiente paso es crear la interfaz de la pagina ApplicationTile.xaml. Para crear la IU, Da clic derecho sobre el proyecto, selecciona Add->New Item. SeleccionaWindows Phone Portrait Page. Nómbralo ApplicationTile, da clic en Add.

  6. Establece el nombre de la aplicación y el titulo de la pagina reemplazando elTitlePanelcon el siguiente código XAML.

    <!--TitlePanel contains the name of the application and page title-->
    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
        <TextBlock x:Name="ApplicationTitle" Text="Tile Sample" Style="{StaticResource PhoneTextNormalStyle}"/>
        <TextBlock x:Name="PageTitle" Text="Application Tile" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}" FontSize="64" />
    </StackPanel>
  7. El código del ApplicationTile se encuentra mas abajo. Aquí te muestro los controles que que lo componen:

    El buttonSetApplicationTiletendra su manejador de evento clic. , reemplaza <Grid x:Name=”ContentPanel” Grid.Row=”1″ Margin=”12,0,12,0″></Grid> de MainPage.xaml con el siguiente código:

    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <TextBlock Height="75" HorizontalAlignment="Left" Margin="12,6,0,0" Name="textBlockDescription" Text="Sets Application Tile properties as a group. Leave text and image properties blank to clear the property. Set Count to 0 to clear the Count property." VerticalAlignment="Top" Width="438" TextWrapping="Wrap" FontSize="16" />
        <TextBlock Height="30" HorizontalAlignment="Left" Margin="164,96,0,0" Name="textBlockTitle" Text="Title" VerticalAlignment="Top" FontSize="18" />
        <TextBox Height="72" HorizontalAlignment="Left" Margin="197,74,0,0" Name="textBoxTitle" Text="" VerticalAlignment="Top" Width="260" />
        <TextBlock Height="30" HorizontalAlignment="Left" Margin="46,171,0,0" Name="textBlockBackgroundImage" Text="Background Image" VerticalAlignment="Top" FontSize="18" />
        <TextBox Height="72" HorizontalAlignment="Left" Margin="197,152,0,0" Name="textBoxBackgroundImage" Text="" VerticalAlignment="Top" Width="260" />
        <TextBlock Height="30" HorizontalAlignment="Left" Margin="23,249,0,0" Name="textBlockCount" Text="Count (1-99, 0=Clear)" VerticalAlignment="Top" FontSize="18" Width="175" />
        <TextBox Height="72" HorizontalAlignment="Left" Margin="197,230,0,0" Name="textBoxCount" Text="" VerticalAlignment="Top" Width="260" InputScope="Number" />
        <TextBlock Height="30" HorizontalAlignment="Left" Margin="127,359,0,0" Name="textBlockBackTitle" Text="BackTitle" VerticalAlignment="Top" FontSize="18" />
        <TextBox Height="72" HorizontalAlignment="Left" Margin="197,338,0,0" Name="textBoxBackTitle" Text="" VerticalAlignment="Top" Width="260" />
        <TextBlock Height="30" HorizontalAlignment="Left" Margin="10,436,0,0" Name="textBlockBackBackgroundImage" Text="BackBackground Image" VerticalAlignment="Top" FontSize="18" />
        <TextBox Height="72" HorizontalAlignment="Left" Margin="197,416,0,0" Name="textBoxBackBackgroundImage" Text="" VerticalAlignment="Top" Width="260" />
        <TextBlock Height="30" HorizontalAlignment="Left" Margin="97,515,0,0" Name="textBlockContent" Text="BackContent" VerticalAlignment="Top" FontSize="18" />
        <TextBox Height="72" HorizontalAlignment="Left" Margin="197,494,0,0" Name="textBoxBackContent" Text="" VerticalAlignment="Top" Width="260" />
        <Button Content="Set Application Tile Properties" Height="72" HorizontalAlignment="Left" Margin="23,551,23,0" Name="buttonSetApplicationTile" VerticalAlignment="Top" Width="410" FontSize="20" FontFamily="Calibri" Click="buttonSetApplicationTile_Click" />
    </Grid>
  8. El ultimo paso es crear la IU para la pagina SecondaryTile.xaml. Para crear la IU, Da clic derecho sobre el proyecto, selecciona Add->New Item. SeleccionaWindows Phone Portrait Page. Nómbralo ApplicationTile, da clic en Add.

  9. Establece el nombre de la aplicación y el titulo de la pagina reemplazando elTitlePanelcon el siguiente código XAML.

    <!--TitlePanel contains the name of the application and page title-->
    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
        <TextBlock x:Name="ApplicationTitle" Text="Tile Sample" Style="{StaticResource PhoneTextNormalStyle}"/>
        <TextBlock x:Name="PageTitle" Text="Secondary Tile" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}" FontSize="64" />
    </StackPanel>
  10. El código del ApplicationTile se encuentra mas abajo. Aquí te muestro los controles que que lo componen:

    El control checkBoxDisplaySecondaryTile contara con los manejadores de eventos checkboxDisplaySecondaryTile_Checked y checkboxDisplaySecondaryTile_Unchecked. Cada botón manejara un evento clic. Reemplaza <Grid x:Name=”ContentPanel” Grid.Row=”1″ Margin=”12,0,12,0″></Grid> de MainPage.xaml con el siguiente código:

    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <CheckBox Content="Display Secondary Tile " Height="72" HorizontalAlignment="Left" Margin="20,4,0,0" Name="checkBoxDisplaySecondaryTile" VerticalAlignment="Top" Checked="checkBoxDisplaySecondaryTile_Checked" Unchecked="checkBoxDisplaySecondaryTile_Unchecked" />
        <TextBlock Height="33" HorizontalAlignment="Center" Margin="9,91,0,0" Name="textBlockDescription" Text="Sets properties of the secondary Tile individually." VerticalAlignment="Top" Width="441" TextAlignment="Center" />
        <TextBox Height="72" HorizontalAlignment="Left" Margin="9,127,0,0" Name="textBoxTitle" Text="" VerticalAlignment="Top" Width="260" />
        <Button Content="Set Title" Height="72" HorizontalAlignment="Left" Margin="259,127,0,0" Name="buttonSetTitle" VerticalAlignment="Top" Width="200" Click="buttonSetTitle_Click" FontSize="16" />
        <TextBox Height="72" HorizontalAlignment="Left" Margin="9,205,0,0" Name="textBoxBackgroundImage" Text="" VerticalAlignment="Top" Width="260" />
        <Button Content="Set Background" Height="72" HorizontalAlignment="Left" Margin="259,205,0,0" Name="buttonSetBackgroundImage" VerticalAlignment="Top" Width="200" FontSize="16" Click="buttonSetBackgroundImage_Click" />
        <TextBox Height="72" HorizontalAlignment="Left" Margin="9,283,0,0" Name="textBoxCount" Text="" VerticalAlignment="Top" Width="260"  InputScope="Number"/>
        <Button Content="Set Count(1-99,0=Clear)" Height="72" HorizontalAlignment="Left" Margin="259,283,0,0" Name="buttonSetCount" VerticalAlignment="Top" Width="200" Click="buttonSetCount_Click" FontSize="14" />
        <TextBox Height="72" HorizontalAlignment="Left" Margin="9,391,0,0" Name="textBoxBackTitle" Text="" VerticalAlignment="Top" Width="260" />
        <Button Content="Set BackTitle" Height="72" HorizontalAlignment="Left" Margin="259,391,0,0" Name="buttonSetBackTitle" VerticalAlignment="Top" Width="200" Click="buttonSetBackTitle_Click" FontSize="16" />
        <TextBox Height="72" HorizontalAlignment="Left" Margin="9,469,0,0" Name="textBoxBackBackgroundImage" Text="" VerticalAlignment="Top" Width="260" />
        <Button Content="Set BackBackground" Height="72" HorizontalAlignment="Left" Margin="259,469,0,0" Name="buttonSetBackBackgroundImage" VerticalAlignment="Top" Width="200" FontSize="16" Click="buttonSetBackBackgroundImage_Click" />
        <TextBox Height="72" HorizontalAlignment="Left" Margin="9,547,0,0" Name="textBoxBackContent" Text="" VerticalAlignment="Top" Width="260" />
        <Button Content="Set BackContent" Height="72" HorizontalAlignment="Left" Margin="259,547,0,0" Name="buttonSetBackContent" VerticalAlignment="Top" Width="200" FontSize="16" Click="buttonSetBackContent_Click" />
    </Grid>

Implementando MainPage

Ahora entrando en materia de la MainPage.xaml.cs, debemos agregar el manejador de eventos de los botones buttonChangeApplicationTile y buttonChangeSecondaryTile. Dentro de la clase MainPage, agrega el siguiente código:

private void buttonChangeApplicationTile_Click(object sender, RoutedEventArgs e)
{
    this.NavigationService.Navigate(new Uri("/ApplicationTile.xaml", UriKind.Relative));
}

private void buttonChangeSecondaryTile_Click(object sender, RoutedEventArgs e)
{
    this.NavigationService.Navigate(new Uri("/SecondaryTile.xaml?DefaultTitle=FromMain", UriKind.Relative));
}

Implementando la pagina ApplicationTile

  1. Para implementar los manejadores de eventos en esta pagina, como trabajaremos con recursos de mosaicos, agrega la siguiente directiva en el tope de la claseApplicationTile:
    using Microsoft.Phone.Shell;
  2. Ahora agrega el siguiente código dentro de la clase. Este implementara el manejador del evento buttonSetApplicationTile_Click. Tomara los valores ingresados en los text box y establecer todas las propiedades en el mosaico de una vez:

    // Set all the properties of the Application Tile.
    private void buttonSetApplicationTile_Click(object sender, RoutedEventArgs e)
    {
        int newCount = 0;
    
        // Application Tile is always the first Tile, even if it is not pinned to Start.
        ShellTile TileToFind = ShellTile.ActiveTiles.First();
    
        // Application should always be found
        if (TileToFind != null)
        {
            // if Count was not entered, then assume a value of 0
            if (textBoxCount.Text == "")
            {
                // A value of '0' means do not display the Count.
                newCount = 0;
            }
            // otherwise, get the numerical value for Count
            else
            {
                newCount = int.Parse(textBoxCount.Text);
            }
    
            // Set the properties to update for the Application Tile.
            // Empty strings for the text values and URIs will result in the property being cleared.
            StandardTileData NewTileData = new StandardTileData
            {
                Title = textBoxTitle.Text,
                BackgroundImage = new Uri(textBoxBackgroundImage.Text, UriKind.Relative),
                    Count = newCount,
                    BackTitle = textBoxBackTitle.Text,
                    BackBackgroundImage = new Uri(textBoxBackBackgroundImage.Text, UriKind.Relative),
                    BackContent = textBoxBackContent.Text
            };
    
            // Update the Application Tile
            TileToFind.Update(NewTileData);
        }
    }

Implementando la pagina SecondaryTile

  1. Para implementar los manejadores de eventos en esta pagina, como trabajaremos con recursos de mosaicos, agrega la siguiente directiva en el tope de la claseApplicationTile:

    using Microsoft.Phone.Shell;
  2. En el manejador de evento OnNavigatedTo, debemos chequear si ya hay mosaicos secundarios existentes y asignar el checkbox correspondiente. El valor por defecto para titulo es establecido aquí también, dependiendo de la asignación de DefaultTitle en el QueryString.

    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);
    
        ShellTile TileToFind = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("DefaultTitle=FromTile"));
        checkBoxDisplaySecondaryTile.IsChecked = (TileToFind != null);
        textBoxTitle.Text = this.NavigationContext.QueryString["DefaultTitle"];
    }
  3. Agrega el siguiente código que implementa el manejador de evento checkBoxDisplaySecondaryTile_Checked. Este código chequea si un tile con un ID designado previamente ya existe. Si no existe, el código crea un objeto StandardTileData y lo usa para establecer las propiedades de la cara frontal y trasera del mosaico.

    private void checkBoxDisplaySecondaryTile_Checked(object sender, RoutedEventArgs e)
    {
        ShellTile TileToFind = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("DefaultTitle=FromTile"));
    
        if (TileToFind == null)
        {
            StandardTileData NewTileData = new StandardTileData
            {
                BackgroundImage = new Uri("Red.jpg", UriKind.Relative),
                Title = "Secondary Tile",
                Count = 12,
                BackTitle = "Back of Tile",
                BackContent = "Welcome to the back of the Tile",
                BackBackgroundImage = new Uri("Blue.jpg", UriKind.Relative)
            };
    
            ShellTile.Create(new Uri("/SecondaryTile.xaml?DefaultTitle=FromTile", UriKind.Relative), NewTileData);
        }
    }
  4. Agrega el siguiente código que implementa el manejador de evento  checkBoxDisplaySecondaryTile_Unchecked. Este código busca un mosaico con el ID que le dimos cuando fue creado, y lo remueve de la pantalla de inicio:

    private void checkBoxDisplaySecondaryTile_Unchecked(object sender, RoutedEventArgs e)
    {
        ShellTile TileToFind = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("DefaultTitle=FromTile"));
    
        if (TileToFind != null)
        {
            TileToFind.Delete();
        }
    }
  5. Agregamos cada manejador de evento clic a los botones. Cada manejador de evento busca por el mosaico a actualizar, toma el nuevo valor tomado del text box correspondiente, y actualiza el mosaico con el nuevo valor.

    // Handle the Title button clicked event by setting the front of Tile title.
    private void buttonSetTitle_Click(object sender, RoutedEventArgs e)
    {
        // Find the Tile we want to update.
        ShellTile TileToFind = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("DefaultTitle=FromTile"));
    
        // If the Tile was found, then update the Title.
        if (TileToFind != null)
        {
            StandardTileData NewTileData = new StandardTileData
            {
                Title = textBoxTitle.Text
            };
    
                    TileToFind.Update(NewTileData);
        }
    }
    
    // Handle the Background Image button clicked event by setting the front of Tilebackground image.
    private void buttonSetBackgroundImage_Click(object sender, RoutedEventArgs e)
    {
        // Find the Tile we want to update.
        ShellTile TileToFind = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("DefaultTitle=FromTile"));
    
        // If the Tile was found, then update the background image.
        if (TileToFind != null)
        {
            StandardTileData NewTileData = new StandardTileData
            {
                BackgroundImage = new Uri(textBoxBackgroundImage.Text, UriKind.Relative)
            };
    
                    TileToFind.Update(NewTileData);
        }
    }
    
    // Handle the Count button clicked event by setting the front of Tile count value.
    private void buttonSetCount_Click(object sender, RoutedEventArgs e)
    {
        int newCount = 0;
    
        // Find the Tile we want to update.
        ShellTile TileToFind = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("DefaultTitle=FromTile"));
    
        // If the Tile was found, then update the count.
        if (TileToFind != null)
        {
            // if Count was not entered, then assume a value of 0.
            if (textBoxCount.Text == "")
            {
                newCount = 0;
            }
            // Otherwise, get the numerical value for Count.
            else
            {
                newCount = int.Parse(textBoxCount.Text);
            }
    
            StandardTileData NewTileData = new StandardTileData
            {
                Count = newCount
            };
    
            TileToFind.Update(NewTileData);
        }
    }
    
    // Handle the Back Title button clicked event by setting the back of Tile title.
    private void buttonSetBackTitle_Click(object sender, RoutedEventArgs e)
    {
        // Find the Tile we want to update.
        ShellTile TileToFind = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("DefaultTitle=FromTile"));
    
        // If the Tile was found, then update the title on the back of the Tile.
        if (TileToFind != null)
        {
            StandardTileData NewTileData = new StandardTileData
                    {
                        BackTitle = textBoxBackTitle.Text
                    };
    
            TileToFind.Update(NewTileData);
        }
    }
    
    // Handle the Back Background Image button clicked event by setting the back of Tile background image.
    private void buttonSetBackBackgroundImage_Click(object sender, RoutedEventArgs e)
    {
        // Find the Tile we want to update.
        ShellTile TileToFind = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("DefaultTitle=FromTile"));
    
        // If the Tile was found, then update the background image on the back of the Tile.
        if (TileToFind != null)
        {
            StandardTileData NewTileData = new StandardTileData
            {
                BackBackgroundImage = new Uri(textBoxBackBackgroundImage.Text, UriKind.Relative)
            };
    
            TileToFind.Update(NewTileData);
        }
    }
    
    // Handle the Back Content button clicked event by setting the back of Tile content.
    private void buttonSetBackContent_Click(object sender, RoutedEventArgs e)
    {
        // Find the Tile we want to update.
        ShellTile TileToFind = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("DefaultTitle=FromTile"));
    
        // If the Tile was found, then update the content on the back of the Tile.
        if (TileToFind != null)
        {
            StandardTileData NewTileData = new StandardTileData
                {
                    BackContent = textBoxBackContent.Text
                };
    
            TileToFind.Update(NewTileData);
        }
    }

Finalmente, has completado el ejemplo para crear, eliminar y actualizar mosaicos secundarios.

  1. Presiona F5 para comenzar a depurar el proyecto. Se ejecutara la aplicación en el emulador.

  2. Navega hacia la pagina Change Application Tile. Establece algunas propiedades para el mosaico de la aplicación como se muestra en el siguiente screenshot y da clic sobre el botón Set Application Tile Properties.

  3. Para ver los resultados de las propiedades que has establecido, navega hacia la pagina de inicio dando un clic sobre el botón Start en el emulador del teléfono. Navega hacia la lista de las aplicaciones instaladas y busca TileSample. Realiza un Tap y Hold (Clic dejándolo presionado unos segundos) sobre TileSample y luego selecciona el comando Pin to start. El emulador te navegara hacia la pagina de inicio mostrándote el mosaico agregado en la pagina de inicio con las propiedades que estableciste en la aplicación.

  4. Presiona el botón Back en el emulador para regresar a la aplicación. PresionandoBack, tu sesión de depuración no ha finalizado.

  5. Presiona el botón Back de nuevo para navegar hacia la pagina principal de la aplicación.

  6. Navega hacia la pagina SecondaryTile y da clic sobre un check box para crear un mosaico secundario. El teléfono te llevara a la pagina de inicio, mostrando el nuevo mosaico agregado.

  7. Presiona el botón Back en el emulador para regresar a la aplicación.

  8. Ingresa un nuevo valor para la propiedad Tile y da clic sobre el botón Set Title.

  9. Navega hacia la pagina de inicio dando un clic sobre el botón Start en el emulador del teléfono. Veras la nueva propiedad Title desplegada en el mosaico.

  10. Ahora presiona el botón Backe intenta cambiar otras propiedades.

  11. Desde la pagina de Inicio, intenta dar clic sobre un mosaico secundario, y veras que la aplicación TileSample se ejecutara y navegara directamente sobre la paginaSecondaryTile. El valor por defecto de Title es FromTile.

Como puedes darte cuenta, debes tomar muy en serio el diseño grafico del mosaico de tu aplicación, a fin de respetar el espacio del nombre del mismo en la esquina izquierda inferior, y la zona del contador indicador de algún evento. Utiliza un fondo de un color solido y evita los gradientes, en el caso que quieras regirte ante los principios de la interfaz Metro, y así aumentas las posibilidades que el usuario lo encuentre estéticamente agradable para anclarlo a su pantalla de inicio.

Autor: Jorge Ramirez      Síguelo en twitter @JorgeRamirezMSP
Publicación original –> http://j.mp/ZlGPO5
Fuente 1 –> http://j.mp/13dWjZ7

Anuncios

1 comentario

Archivado bajo Windows Phone

Una respuesta a “Generation App – Día 10 – Trabajar con mosaicos en Windows Phone

  1. Pingback: Con Generation App nunca fue tan fácil desarrollar para Windows Phone « El Blog de MSP para Latinoamerica [BETA]

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s