Création d'une expérience utilisateur optimale pour l'impression dans Windows 8

Blog des développeurs d'applications Windows 8

Indications sur la conception d'applications de style Metro pour Windows 8, par l'équipe d'ingénierie de Windows 8

Création d'une expérience utilisateur optimale pour l'impression dans Windows 8

  • Comments 1

En réimaginant Windows, nous avons profité de l'occasion pour repenser tous les aspects de l'impression (expérience utilisateur, plateforme de développement et écosystème matériel) et la façon dont les différents éléments interagissent pour aboutir à une formidable expérience globale. Dans ce billet, je présente l'expérience utilisateur et la plateforme de développement pour l'impression dans Windows 8. J'explique également comment vous pouvez adapter l'expérience utilisateur aux besoins de votre application.

Impression à partir des applications Windows 8

Commençons par examiner comment fonctionne l'impression dans Windows 8. Nous étudierons dans un second temps comment les différents types d'applications sont susceptibles de gérer l'impression.

Dans Windows 8, l'impression dépend du contexte de l'application qui la prend en charge. Une application prend en charge l'impression en souscrivant au contrat d'impression. En tant que développeur, vous décidez quand votre application prend en charge l'impression et quand elle ne la prend pas en charge. Toutes les applications n'ont pas besoin d'imprimer leurs contenus. Par exemple, si vous développez un jeu, vous pouvez très bien décider de ne pas prendre en charge l'impression. En revanche, si vous travaillez sur une application destinée à une compagnie aérienne, par exemple, la possibilité d'imprimer une carte d'embarquement constituera sans doute l'un des principaux aspects du processus d'enregistrement. Vous seul décidez si votre application doit prendre en charge l'impression et quand elle doit le faire. Néanmoins, vous devez tenir compte des attentes de vos clients. Ainsi, si vos clients souhaitent pouvoir imprimer des contenus à partir de votre application, nous vous recommandons de prendre en charge l'impression.

Pour imprimer des documents dans Windows 8, l'utilisateur doit effectuer un balayage à partir du bord droit de l'écran pour afficher la barre d'icônes. Lorsqu'une application prend en charge l'impression, un appui sur l'icône Périphériques affiche toutes les imprimantes installées sur votre ordinateur. Lorsque vous sélectionnez l'imprimante de destination, vous voyez la fenêtre d'impression ci-dessous.

Procédure d'impression

Procédure d'impression

La fenêtre d'impression affiche un aperçu du document qui sera imprimé, ainsi que quelques paramètres d'impression couramment utilisés. Lors de la conception des fonctionnalités d'impression, nous avons réalisé que les utilisateurs souhaitent bien souvent visualiser le contenu avant de l'imprimer. Aussi, la plateforme d'impression affiche un aperçu du contenu à imprimer, directement dans la fenêtre d'impression : vous n'avez plus besoin de chercher comment afficher l'aperçu à partir de l'application. La plateforme d'impression vous permet également d'actualiser l'aperçu, de façon à ce que l'utilisateur puisse voir à quoi ressemblera le résultat lorsqu'il modifie les différents paramètres d'impression dans la fenêtre d'impression.

Pour optimiser l'expérience utilisateur, par défaut la fenêtre d'impression affiche uniquement trois paramètres d'impression : Copies, Orientation et Couleur. D'après nos enquêtes, il s'agit là des paramètres d'impression les plus couramment modifiés par les utilisateurs. En affichant ces paramètres, l'utilisateur peut accéder rapidement aux paramètres qu'il utilise le plus pour configurer une tâche d'impression. En tant que développeur, vous pouvez définir les paramètres à afficher dans la fenêtre d'impression, pour offrir l'expérience utilisateur la mieux adaptée à votre application. Vous pouvez également définir la valeur par défaut de chaque paramètre.

Toutes les applications Windows 8 font appel à la même expérience utilisateur pour l'impression des contenus. Ainsi, lorsqu'un utilisateur sait comment imprimer à partir d'une application, il connaît la procédure pour toutes les applications. Par conséquent, les utilisateurs n'ont pas besoin de fouiller dans les options pour trouver la fonction d'impression, ni d'apprendre une nouvelle procédure pour chaque application.

Contrat d'impression

Pour communiquer avec la plateforme d'impression, votre application utilise le contrat d'impression. Votre application fournit le contenu à imprimer et Windows apporte l'expérience d'impression et l'infrastructure sous-jacente. Si votre application souscrit au contrat d'impression, l'impression est possible à partir de l'icône Périphériques, facilement accessible et simple d'utilisation.

Comme toutes les API WinRT, le contrat d'impression a été conçu pour fonctionner avec le langage et le framework d'interface de votre choix. Ainsi, que vous utilisiez du code HTML ou XAML pour mettre en forme vos contenus, vous pouvez exploiter les fonctions d'impression. Si vous souhaitez contrôler de façon plus précise la manière dont votre application imprime son contenu, vous pouvez même utiliser des technologies D2D ou XPS.

Lorsque vous ajoutez la prise en charge de l'impression à votre application, votre travail passe par deux aspects essentiels :

  • Fournir le contenu à imprimer.
  • Déterminer les paramètres d'impression qui fonctionnent le mieux avec votre application.

Examinons chacun de ces deux éléments.

Fournir le contenu à imprimer

Lors des phases de conception de votre application, prenez le temps de réfléchir aux scénarios d'impression. Quels sont les contenus que les utilisateurs sont susceptibles de vouloir emporter ? Quels sont les contenus dont ils voudront disposer d'un exemplaire papier, utilisable et consultable ultérieurement ? Si votre application prend des photos, par exemple, l'utilisateur souhaitera-t-il les imprimer et les encadrer pour les accrocher au mur ? En réfléchissant aux scénarios d'utilisation de votre application, vous pourrez mieux choisir les contenus qui doivent pouvoir être imprimés à partir de votre application et concevoir ainsi la meilleure expérience d'impression possible pour vos clients.

Une fois que vous avez identifié les contenus à imprimer, essayez d'identifier le point de collecte idéal pour ces contenus. Pour commencer, n'oubliez pas qu'une disposition qui semble parfaite à l'écran ne l'est pas forcément sur papier. Vous devez trouver le meilleur moyen de mettre en forme vos contenus pour chacun de ces types de sortie. Ainsi, vous imprimerez probablement des contenus différents de la vue principale de votre application, qui correspond au contenu affiché à l'écran. Ce principe s'applique à tous les types d'applications, y compris aux applications simples telles que les lecteurs de flux d'actualités. Si la présentation en colonnes est idéale à l'écran pour vos contenus, elle ne le sera pas forcément pour ces mêmes contenus une fois imprimés. Tous ces aspects influent sur la façon dont vous créez votre application, et il est plus simple de les étudier au début du processus de développement que de revenir en arrière par la suite pour intégrer des modifications.

Il peut également être judicieux d'étudier comment l'impression s'intègre aux scénarios d'utilisation de votre application. Dans de nombreuses applications, l'impression n'est qu'un simple élément de menu. Par exemple, un utilisateur peut vouloir imprimer la photo affichée. Dans ce cas, l'icône Périphériques est idéale pour lui permettre de lancer une impression. Aussi, il convient dans ce cas de ne pas ajouter de fonction d'impression dans l'application : utilisez simplement l'icône du système. Par opposition, dans d'autres cas, l'impression constitue une étape importante des méthodes d'utilisation générales de l'application. Prenons l'exemple d'une application de commerce en ligne qui permet d'imprimer des reçus. La vue affichée à l'écran peut très bien fournir une confirmation de commande et remercier le client pour son achat, mais aussi inclure un bouton Imprimer le reçu, permettant à l'utilisateur d'accéder directement à la fonction d'impression. Lorsque l'utilisateur appuie sur ce bouton Imprimer le reçu, la fenêtre d'impression s'ouvre et affiche un aperçu. L'utilisateur peut alors imprimer le reçu directement, en fonction de ce qu'il voit sur l'aperçu, comme sur l'image suivante :

Le contenu à imprimer diffère de la vue affichée à l'écran

Le contenu à imprimer diffère de la vue affichée à l'écran

Impression à partir d'une application HTML/JavaScript

Pour prendre en charge l'impression dans votre application, il vous suffit d'ajouter ces lignes de code.

// Register for print contract
var printManager = Windows.Graphics.Printing.PrintManager.getForCurrentView();
printManager.onprinttaskrequested = onPrintTaskRequested;
function onPrintTaskRequested(printEvent) {
printEvent.request.createPrintTask("Print Sample", function (args) {
args.setSource(MSApp.getHtmlPrintDocumentSource(document));
});
}

Ces lignes de code permettent à votre application de souscrire au contrat d'impression. Lorsque l'utilisateur lance une impression, l'application imprime simplement le contenu du document actuel, tel qu'il est affiché à l'écran. Vous pouvez alors imprimer des contenus à partir de votre application, par le biais de l'icône Périphériques. Votre application profite de l'expérience d'impression et des paramètres d'impression par défaut. Le moteur de rendu de Windows 8 gère la pagination et l'actualisation des aperçus.

Dans d'autres situations, vous souhaitez contrôler le contenu à imprimer et comment le mettre en page. Par exemple, vous pouvez vouloir imprimer du contenu qui n'est actuellement pas visible à l'écran, par exemple du contenu qui ne se trouve pas dans le DOM actuel (comme l'exemple d'impression de reçu déjà mentionné). Pour cela, le moyen le plus simple consiste à définir le contenu secondaire dans l'élément d'en-tête de votre code HTML, comme ci-dessous.

<! -- Add this to the head element of your html file -->
<link rel="alternate" href="http://go.microsoft.com/fwlink/?linkid=240076" media="print"/>

Lorsque vous utilisez cette méthode, l'appel de getHtmlPrintDocumentSource(document) utilise correctement le contenu secondaire spécifié.

Comment faire si vous souhaitez profiter de plus de créativité ? Bonne nouvelle : à partir du moment où vous pouvez transmettre un document HTML à getHtmlPrintDocumentSource, vous pouvez imprimer du contenu HTML à partir de n'importe où ou presque, qu'il s'agisse de contenus créés localement, de contenus téléchargés sur le Web dans un IFrame ou de tout autre contenu à partir duquel vous souhaitez créer un document imprimé.

Vous pouvez également utiliser des contrôles de disposition complexes (disposition multicolonne, défilement horizontal, regroupement d'éléments, etc.) pour créer votre expérience d'affichage. Ces dispositions ne sont pas forcément adaptées à l'impression. Il est par conséquent indispensable de simplifier la disposition avant d'envoyer le contenu à la plateforme d'impression, pour paginer facilement le contenu et afficher un aperçu du rendu, ce que vous pouvez effectuer à l'aide de règles de média CSS. La définition de règles CSS spécifiques aux supports d'impression facilite la création d'une disposition différente de ce que l'utilisateur affiche dans le flux de votre application. Grâce à CSS, vous pouvez masquer du contenu, redimensionner des éléments, ajuster les marges, supprimer des éléments (arrière-plans et barres de défilement, modifier les polices et les couleurs, etc.). Prenons un exemple.

Imaginons une application de recettes de cuisine qui vous permet d'imprimer vos recettes favorites. Cette application s'appuie sur le modèle Application grille (Fichier->Nouveau projet-><Langage>->Windows Store->Application grille).

Application de recettes de cuisine

Application de recettes de cuisine

La première chose à faire est de réfléchir au contenu que vous devez réellement imprimer. Supposons que la personne qui imprime le contenu a l'intention de l'ajouter à un livre de recettes et se préoccupe donc peu des notes et des avis. Nous allons donc imprimer le titre, l'image, la description, la liste des ingrédients et les instructions. Nous n'imprimerons pas le reste du contenu (avis, commentaires, etc.).

Voici à quoi ressemble le fichier CSS permettant d'afficher le contenu à l'écran.

.itemdetailpage .content {
-ms-grid-row: 1;
-ms-grid-row-span: 2;
display: block;
height: 100%;
overflow-x: auto;
position: relative;
width: 100%;
z-index: 0;}

.itemdetailpage .content article {
/* Define a multi-column, horizontally scrolling article by default. */
column-fill: auto;
column-gap: 80px;
column-width: 480px;
height: calc(100% - 183px);
margin-left: 120px;
margin-top: 133px;
width: 480px;}

.itemdetailpage .content article header .item-title {
margin-bottom: 19px;}

.itemdetailpage .content article .item-image {
height: 240px;
width: 460px;}

.itemdetailpage .content article .item-rating {
height: 40px;
margin-top: 0px}

.itemdetailpage .content article .item-review {
height: 100px;
margin-top: 20px }

.itemdetailpage .content article .item-content p {
margin-top: 10px;
margin-bottom: 20px;
margin-right: 20px;}

Voici ce que vous voyez dans l'aperçu avant impression.

Impression sans mise en forme du contenu

Impression sans mise en forme du contenu

Cet aperçu avant impression présente quelques problèmes. Ainsi, le bouton Précédent apparaît à côté du titre et une barre de défilement est affichée. En outre, vous ne voyez l'aperçu que pour la première page. Au final, l'aperçu n'est pas exploitable.

Le problème ici est que lorsque le contenu de l'application est trop grand pour être affiché à l'écran, la propriété overflow ajoute une barre de défilement pour permettre de faire défiler le contenu masqué. Lorsque vous envoyez du contenu à imprimer, le même comportement est adopté et le contenu est tronqué. Pour que la disposition adéquate du contenu soit envoyée à la plateforme d'impression, le contenu doit être mis en forme à l'aide des règles CSS.

Pour mettre en forme le contenu à imprimer, vous créez un fichier CSS (print.css) et vous l'ajoutez au fichier html.

<link rel="stylesheet" type="text/css" href="/css/print.css" media="print" />
Print.css
/* Hide the back button */
.win-backbutton {
display: none;}

/* Remove the grid layout */
.fragment {
display: block;
height: auto;
width: 100%;
position: relative;
margin: 0px;
overflow: visible;}

/* Remove the header */
.fragment header[role=banner] {
display: none;}

/* Remove multicolumn layout */
/* Resize the content to take up available space*/
/* Remove scrolling behavior */
.itemdetailpage .content {
display: block;
height: 100%;
overflow: visible;
width: 100%;}

.itemdetailpage .content article {
height: 100%;
width: 100%;
margin: 0px;
overflow: visible;}

/* Adjust margins */
/* Increase font sizes */
.itemdetailpage .content article header .item-title {
margin-bottom: 29px;
font-size: 450%;}

.itemdetailpage .content article .item-image {
height: 480px;
width: 920px;
margin-top: 20px;
margin-bottom: 40px;}

/* Remove rating and review controls */
.itemdetailpage .content article .item-rating {
display: none;}
.itemdetailpage .content article .item-review {
display: none; }

.itemdetailpage .content article .item-content p {
height: auto;
width: 100%;}

L'aperçu avant impression est ainsi mis en forme et l'impression ressemble à l'image ci-dessous.

Impression avec mise en forme du contenu

Impression avec mise en forme du contenu

Vous remarquerez que les problèmes évoqués précédemment sont ici éliminés. Le bouton Précédent ne s'affiche plus près du titre et la barre de défilement ne s'affiche pas non plus. En accédant à la page suivante de l'aperçu, vous pouvez constater que le contenu à imprimer est correctement mis en page. CSS s'avère être un outil puissant pour mettre en page le contenu en fonction de vos besoins.

Pour plus d'informations sur l'impression à partir d'une application écrite en HTML et JavaScript, voir Impression à l'aide de JavaScript et HTML.

Impression à partir des applications XAML

Si vous développez votre application en XAML, vous devez gérer une plus grande partie du travail d'impression au sein de l'application. Vous devez définir la mise en page du contenu pour votre application et déterminer les conséquences de la pagination. Ainsi, vous pouvez contrôler le contenu de chaque page pour déterminer exactement le contenu que vous souhaitez imprimer à partir de votre application. Comme vous pouvez l'imaginer, vous pouvez utiliser XAML pour définir la disposition du contenu imprimé dans votre application, comme vous utilisez XAML pour définir la disposition du contenu affiché à l'écran.

XAML est un fantastique langage descriptif offrant beaucoup de flexibilité pour l'affichage de contenu à l'écran, en particulier lorsque votre application doit être mise à l'échelle de façon adéquate pour s'adapter à différentes dimensions d'écran. Néanmoins, les atouts de XAML pour l'affichage à l'écran ne se retrouvent pas forcément sur papier. Par exemple, les dispositions XAML mettent souvent à l'échelle les polices et les images pour s'adapter aux pixels horizontaux et verticaux de l'écran. Si tout cela fonctionne parfaitement à l'écran, en général les utilisateurs ne souhaitent pas que leurs impressions soient mises à l'échelle. Vous devez par conséquent réfléchir à la manière dont le contenu imprimé dans votre application doit être mis en page, puis veiller à ce que le code XAML que vous utilisez reflète parfaitement vos intentions.

Revenons à notre application de recettes de cuisine et examinons comment modifier la disposition du contenu en XAML. En XAML, le contenu qui nous intéresse se trouve dans l'élément ItemDetailPage du contrôle richTextColumns. Pour obtenir les informations que nous souhaitons imprimer (titre, image, description, liste des ingrédients et instructions), vous définissez une page de recettes sous la forme d'une liste de conteneurs associés les uns aux autres.

<Grid VerticalAlignment="Center" x:Name="grid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>

<Grid.RowDefinitions>
<RowDefinition Height="3*"/>
<RowDefinition Height="7*"/>
</Grid.RowDefinitions>

<RichTextBlock x:Name="txtContent" OverflowContentTarget="{Binding ElementName=link}" Grid.Row="0" Grid.Column="0">
<Paragraph TextAlignment="Center">
<Run x:Name="txtRecipe" Text="{Binding Title}" FontSize="30" Foreground="Black"></Run>
</Paragraph>
<Paragraph>
<InlineUIContainer>
<Image x:Name="imgRecipe" Stretch="Uniform" Source="{Binding Image}"/>
</InlineUIContainer>
</Paragraph>
<Paragraph>
<Run Text="Ingredients:" FontSize="30" Foreground="Black"/>
<Run x:Name="txtIngredients" Text="{Binding RecipeIngredients}" FontSize="20" Foreground="Black"/>
</Paragraph>
<Paragraph>
<Run Text="Details:" FontSize="30" Foreground="Black"/>
<Run x:Name="txtDetails" Text="{Binding Content}" FontSize="20" Foreground="Black"/>
</Paragraph>
</RichTextBlock>

<RichTextBlockOverflow x:Name="link" Grid.Row="1" Grid.Column="0"/>
</Grid>

Si la recette de cuisine est trop grande pour tenir sur la page, l'application doit créer des pages supplémentaires contenant le contenu qui dépasse. Dans ce cas, la page supplémentaire contient simplement un élément RichTextBlockOverlow qui est lié à l'élément de bloc de texte enrichi de la page précédente, de sorte que le texte restant apparaisse sur la page suivante.

<Grid x:Name="grid">
<RichTextBlockOverflow x:Name="link"/>
</Grid>

En réponse à la pagination, vous pouvez définir votre algorithme de projection des pages comme ceci :

void printDocument_Paginate(object sender, PaginateEventArgs e)
{
PrintDocument printDocument = (PrintDocument)sender;

// get printer page description
PrintPageDescription pageDesc = e.PrintTaskOptions.GetPageDescription(0);

// clear previous generated print content
pages.Clear();
printingRoot.Children.Clear();

RecipePage page = new RecipePage(pageDesc)
{
DataContext = flipView.SelectedItem
};

UIElement element = null;
RichTextBlockOverflow rtbo = page.Link;

do
{
// check if this is the first page
if (element != null)
{
var continuation = new ContinuationPage(rtbo, pageDesc);
element = continuation;
rtbo = continuation.Link;
}
else
{
element = page;
}

// add the page to the visual tree to forece content flow
printingRoot.Children.Add(element);
printingRoot.InvalidateMeasure();
printingRoot.UpdateLayout();

pages.Add(element);

} while (rtbo.HasOverflowContent);

// set the current number of pages
printDocument.SetPreviewPageCount(pages.Count, PreviewPageCountType.Intermediate);
}

Pour plus d'informations sur l'impression à partir d'une application écrite en XAML, voir Impression à l'aide de C#/VB/C++ et XAML.

Déterminer les paramètres d'impression qui fonctionnent le mieux avec votre application

Une fois que vous savez quels contenus doivent pouvoir être imprimés à partir de votre application et comment vous souhaitez que ce contenu s'affiche, prenez le temps de réfléchir aux expériences utilisateur que vous souhaitez que votre application fournisse.

Vous vous rendrez peut-être compte alors que l'expérience par défaut offerte par les trois paramètres d'impression ne suffit pas. Il peut ainsi être utile d'afficher des paramètres d'impression supplémentaires ou d'ajouter vos propres paramètres spécifiques dans la fenêtre d'impression. Dans ce cas, vous pouvez personnaliser l'expérience d'impression en fonction de vos besoins.

Examinons quelques exemples.

Ajout de paramètres d'impression

Pour reprendre l'exemple de l'application de cuisine, nous savons que les recettes peuvent facilement être réparties sur plusieurs pages. Par conséquent, il peut être utile d'offrir la possibilité d'imprimer sur les deux côtés de la feuille. Pour cela, vous pouvez ajouter le paramètre Impression recto-verso à la fenêtre d'impression.

La fenêtre d'impression ressemble alors à ceci :

Impression à l'aide de paramètres d'impression supplémentaires

Impression à l'aide de paramètres d'impression supplémentaires

Voici comment ajouter le paramètre Impression recto-verso en JavaScript :

printTask.options.displayedOptions.append
(Windows.Graphics.Printing.StandardPrintTaskOptions.duplex);

Voici maintenant comment ajouter le paramètre Impression recto-verso en C# :

printTask.options.displayedOptions.Add (Windows.Graphics.Printing.StandardPrintTaskOptions.Duplex);

L'impression recto-verso fait partie des nombreux paramètres d'impression à votre disposition. Cependant, il ne suffit pas de demander l'affichage de ce paramètre pour qu'il apparaisse. En effet, si l'imprimante ne prend pas en charge l'impression recto-verso, Windows masque le paramètre pour l'utilisateur. Pour plus d'informations sur l'ajout de paramètres d'impression, voir Comment modifier les options standard dans la fenêtre d'impression pour les applications HTML/JavaScript et XAML.

Ajout de paramètres personnalisés aux applications XAML

Vous pouvez personnaliser encore plus vos applications XAML. Ainsi, vous pouvez ajouter vos propres paramètres d'impression personnalisés à la fenêtre d'impression. Prenons un exemple.

Imaginons une application de cartographie qui vous permet d'imprimer des itinéraires. Vous vous dites peut-être que l'impression de cartes est coûteuse, car l'encre est chère, et vous cherchez des moyens pour permettre à l'utilisateur de choisir ce qu'il veut imprimer. Ainsi, vous pouvez vouloir afficher un paramètre personnalisé tel que Type d'itinéraire :

Impression à l'aide de paramètres personnalisés

Impression à l'aide de paramètres personnalisés

Dans cet exemple, l'application a ajouté le paramètre Type d'itinéraire, qui offre trois options : Carte et texte, Carte uniquement et Texte uniquement. Ainsi, l'utilisateur peut choisir comment imprimer la carte.

Voici comment ajouter une option personnalisée de ce type :

PrintCustomItemListOptionDetails pageFormat = printDetailedOptions.CreateItemListOption 
("PageContent", "Pictures");
pageFormat.AddItem ("MapText", "Map and text");
pageFormat.AddItem ("MapOnly", "Map only");
pageFormat.AddItem ("TextOnly", "Text only");

// Add the custom option to the option list
displayedOptions.Add ("PageContent");

printDetailedOptions.OptionChanged += printDetailedOptions_OptionChanged;

Pour plus d'informations sur cette fonctionnalité, voir Comment ajouter des paramètres personnalisés à la fenêtre d'impression.

Conclusion

Le contrat d'impression offre une grande flexibilité pour décider des contenus à imprimer à partir de votre application et du résultat à obtenir. Il permet aussi aux utilisateurs de lancer des impressions de la même manière à partir de toutes les applications Windows 8. Vous pouvez imprimer des contenus en utilisant l'expérience par défaut ou personnaliser l'expérience d'impression de façon plus précise, en fonction des besoins de votre application. Dans tous les cas, vous contrôlez quelles informations votre application sera capable d'imprimer.

Références

Lien

Types

Exemple de contrat d'impression

Exemple

Souscription au contrat d'impression en HTML/JavaScript

Document

Souscription au contrat d'impression en XAML

Document

Guide de référence de l'espace de noms Windows.Graphics.Printing

Document

Guide de référence de l'espace de noms Windows.Graphics.Printing.OptionDetails

Document

Sangeeta Ranjit, chef de projet senior, Appareils Windows et mise en réseau

Contributions : Darren Davis, Daniel Alex Volcinschi, Saumya Jain, Travis Eby

  • Loading...
Leave a Comment
  • Please add 1 and 7 and type the answer here:
  • Post