Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Développement Cross-Platform avec Titanium Mobile

Xavier Lacot
December 06, 2011

Développement Cross-Platform avec Titanium Mobile

Présentation de Titanium Mobile au Paris Android User Group.

Xavier Lacot

December 06, 2011
Tweet

More Decks by Xavier Lacot

Other Decks in Programming

Transcript

  1. Développement Cross-Platform
    avec Titanium Mobile
    Xavier Lacot – 06 Décembre 2011

    View Slide

  2. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    2
    Qui suis-je ?
    Xavier Lacot
    ■ Clever Age
    ■ Dirige le centre d'expertise
    ■ Leader technique du pôle PHP
    ■ Contributeur à plusieurs projets Open Source
    ■ Développeur Titanium depuis 2009
    ■ Expert frameworks Web
    ■ Vice Président De l'Association Française des Utilisateurs de
    PHP (afup.org)
    ■ http://twitter.com/xavierlacot

    View Slide

  3. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    3
    Sommaire
    1. Pourquoi Titanium mobile ?
    2. Qu'est-ce que Titanium mobile ?
    ■ Mode de fonctionnement
    ■ Principes de développement
    3. Démarrer avec Titanium
    ■ Outillage et Documentation
    4. Tour des APIs disponibles
    5. Démonstration simple

    View Slide

  4. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    4
    Un large panel de solutions disponibles

    View Slide

  5. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    5
    WebApp vs. App natives
    WebApp App native
    Portabilité Navigateur Web : toutes
    plateformes Développement spécifique
    Référencement Moteurs de recherche
    classiques
    Référencement dans les App
    Stores
    Accessibilité Peu de contraintes
    Mode offline impossible
    Dépendant de la validation
    Mode offline possible
    Performance Dépend de la techno du
    serveur, de la connexion, ...
    Performance maximale
    (exécuté sur le mobile)
    Mises à jour Mise à jour instantanée sur le
    serveur
    Dépend du processus de
    validation sur le store
    Effet « Waouw » Limité aux capacités des
    navigateurs mobiles
    Plus de possibilités, plus riche :
    nécessité marketing
    Coût de développement Compétences classiques
    Coût limité
    Compétences plus rares et
    éparses. Coût généralement
    plus élevé.

    View Slide

  6. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    6
    Parts de marché

    View Slide

  7. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    7
    Le choix des développeurs...

    View Slide

  8. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    8
    Constat
    ■ Constat :
    ■ Développements natifs compliqués
    ■ Piles applicatives différentes => plusieurs développements nécessaires
    ■ Difficile d'anticiper les évolutions de chaque système
    ■ Risqué de miser sur des compétences potentiellement inutiles dans les
    années à venir
    ■ Besoin d'un framework d'abstraction
    ■ Mutualiser les développements
    ■ Développer plus rapidement
    ■ Industrialiser (tests unitaires, intégration continue, etc.)
    ■ Établir un choix pérenne

    View Slide

  9. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    9
    Sommaire
    1. Pourquoi Titanium mobile ?
    2. Qu'est-ce que Titanium mobile ?
    ■ Mode de fonctionnement
    ■ Principes de développement
    3. Démarrer avec Titanium
    ■ Outillage et Documentation
    4. Tour des APIs disponibles
    5. Démonstration simple

    View Slide

  10. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    10
    « Titanium is an open source framework
    for building native desktop and mobile
    applications using open web technologies
    (HTML, CSS, and JavaScript) »

    View Slide

  11. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    11
    Titanium mobile
    ■ Framework
    ■ Open Source
    ■ Sponsor : Appcelerator
    ■ Apparu en août 2009
    ■ Développement en javascript
    ■ Cross-Plateformes
    ■ iOS, Android, (BlackBerry)
    ■ Bilan :
    ■ Applications natives avec un look natif
    ■ APIs identiques suivant les cibles
    ■ Look natif → adapté à la plupart de vos applications !

    View Slide

  12. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    12
    Trois bonnes raisons pour Titanium...
    ■ Langages Web très populaires
    ■ Faciles à apprendre
    ■ Très répandus
    ■ Standards ouverts
    ■ Cross platform
    ■ Codez une fois, déployez plusieurs !
    ■ Applications natives
    ■ Rapides
    ■ Mode offline
    ■ Accès aux fonctionnalités matérielles
    ■ Actives en tâche de fond

    View Slide

  13. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    13
    Et encore plus...
    Deux frameworks distincts :
    ■ Un framework « desktop », Titanium Desktop
    ■ Javascript,
    ■ PHP,
    ■ Python,
    ■ Ruby
    ■ Un framework « mobile »... Titanium Mobile !
    ■ HTML / CSS / javascript
    ■ En pratique js principalement, rarement HTML ou CSS

    View Slide

  14. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    14
    Architecture du framework

    View Slide

  15. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    15
    Architecture du framework

    View Slide

  16. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    16
    APIs offertes Titanium

    Titanium.Analytics : statistiques et rapports d'utilisation

    Titanium.API : logging

    Titanium.App : informations liées à l'application

    Titanium.Contacts: carnet d'adresse

    Titanium.Database: bases de données

    Titanium.Filesystem: système de fichiers

    Titanium.Geolocation: géolocalisation

    Titanium.Map: cartographie

    Titanium.Network: réseau

    Titanium.Platform: informations au sujet de la plateforme

    Titanium.UI : tous les éléments d'interface

    etc.

    View Slide

  17. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    17
    Mécanismes de compilation (1/3)
    ■ Analyse des dépendances (API requises, etc.)
    ■ Pré-validation du code javascript
    Compilation
    “cible”
    Pré-compilation Compilation
    “front-end”
    .js

    View Slide

  18. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    18
    Mécanismes de compilation (2/3)
    ■ Compilation des librairies de Titanium
    ■ Préparation à la compilation sur la plateforme
    cible (dépendances, etc.)
    Compilation
    “cible”
    Pré-compilation Compilation
    “front-end”
    .js

    View Slide

  19. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    19
    Mécanismes de compilation (3/3)
    ■ Appel des outils de compilation fournis par les SDKs
    ■ IOS
    ■ transformation du js sous la forme de variables Objective-C
    ■ Interprétation à l'exécution par l'interpréteur javascript de l'iPhone
    ■ Android
    ■ Précompilation en bytecode,
    ■ Interprétation par Rhino (Mozilla) embarqué dans l'appli,
    ■ Bientôt par V8 (Titanium 1.8), bien plus performant
    Compilation
    “cible”
    Pré-compilation Compilation
    “front-end”
    .js

    View Slide

  20. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    20
    Sommaire
    1. Pourquoi Titanium mobile ?
    2. Qu'est-ce que Titanium mobile ?
    ■ Mode de fonctionnement
    ■ Principes de développement
    3. Démarrer avec Titanium
    ■ Outillage et Documentation
    4. Tour des APIs disponibles
    5. Démonstration simple

    View Slide

  21. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    21
    Principes de développement
    Titanium est peu contraignant
    ■ Possibilité d'appliquer des bonnes pratiques
    ■ … ou pas → de nombreux problèmes en perspective !
    Bonnes pratiques :
    ■ Pas de variables globales
    ■ Toujours utiliser l'opérateur de comparaison et non l'opérateur d'égalité
    ■ Utilisez l'opérateur ternaire
    ■ Conception modulaire
    ■ Validation JSLint / JSHint
    ■ Toujours utiliser le point virgule (« ; ») en fin de blocs d'instructions !

    View Slide

  22. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    22
    Pas de variables globales
    // The bad
    var key = 'value',
    foo = 'bar',
    human = 'john';
    function hello(name) {
    alert('Hello ' + world);
    }
    function transform(value) {
    return 'Logging ' + value;
    }
    function log(text) {
    Titanium.API.log(
    transform(text)
    );
    }
    // call the function
    log('Coucou poney!');
    // The good
    var application = {
    key: 'value',
    foo: 'bar',
    human: 'john'
    };
    application.hello = function(name) {
    alert('Hello ' + world);
    };
    (function() {
    // locally defined function
    function transform(value) {
    return 'Logging ' + value;
    }
    application.log = function(text) {
    Titanium.API.log(
    transform(text)
    );
    }
    })();
    // call the function
    application.log('Coucou poney!');

    View Slide

  23. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    23
    Opérateur de comparaison
    Voir http://wtfjs.com/ pour plus d'exemples...
    // utilisez === et non ==
    Ti.API.info(false == 0); // true
    Ti.API.info(false == ''); // true
    Ti.API.info('' == 0); // true
    Ti.API.info(null == 0); // true
    Ti.API.info(undefined == false); // true
    Ti.API.info(NaN == 0); // true
    // attention aux comparaisons de flottants
    Ti.API.info(0.3 + 0.4 === 0.7); // false
    // attention à typeof
    Ti.API.info(typeof null); // 'object'
    Ti.API.info(typeof NaN); // 'number'

    View Slide

  24. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    24
    Règles à ne pas négliger
    ■ À faire
    ■ Utiliser des noms de variable expressifs
    ■ Utiliser les coding standards fournies par Google : http://xav.cc/d7f90
    ■ Commenter votre code
    ■ Valider la syntaxe avec JSLint ou JSHint
    ■ http://www.jshint.com/
    ■ https://github.com/jshint/jshint
    ■ Utiliser de manière extensive (et savoir qu'on le fait) :
    ■ Les closures
    ■ L'héritage par prototypes
    ■ Le “require()” de CommonJS (cf. http://www.commonjs.org)

    View Slide

  25. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    25
    Sommaire
    1. Pourquoi Titanium mobile ?
    2. Qu'est-ce que Titanium mobile ?
    ■ Mode de fonctionnement
    ■ Principes de développement
    3. Démarrer avec Titanium
    ■ Outillage et Documentation
    4. Tour des APIs disponibles
    5. Démonstration simple

    View Slide

  26. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    26
    Titanium Developer
    ■ Abandonné
    début 2011
    ■ Pas d'IDE
    intégré

    View Slide

  27. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    27
    Titanium Studio

    View Slide

  28. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    28
    Titanium Studio
    ■ Titanium Studio
    ■ Aptana, éditeur basé sur Eclipse
    ■ Racheté début 2011
    ■ Forte intégration avec les SDK
    ■ Permet :
    ■ De créer un projet
    ■ Debugger intégré
    ■ Auto-complétion / aide au code
    ■ De lancer les simulateurs / émulateurs iOS et Android
    ■ Inclus au moment de télécharger le framework

    View Slide

  29. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    29
    Premier projet

    View Slide

  30. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    30
    Premier projet
    Project name :
    nom du projet
    App Id :
    identifiant de l'application,
    très important
    Deployment targets :
    choix des plateformes
    cibles

    View Slide

  31. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    31
    Premier projet

    View Slide

  32. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    32
    Contenu d'un projet
    ■ build : dossier de compilation
    ■ Resources :
    ■ le code de l'application
    ■ tous les assets (images, etc.)
    ■ éventuellement une base SQLite
    ■ éventuellement des modules natifs
    ■ tiapp.xml : les directives de configuration
    et de compilation
    ■ Noms, icône et copyright
    ■ Full screen ?
    ■ Analytics ?
    ■ Différents paramètres

    View Slide

  33. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    33
    Cross-platform...

    View Slide

  34. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    34
    Documentation, aide et exemples

    Documentation :

    API : votre meilleure amie ! http://developer.appcelerator.com/apidoc/mobile/latest

    Référence, littérature (assez) exhaustive : http://wiki.appcelerator.org/display/guides/Home

    Aide :

    Questions : http://developer.appcelerator.com/questions

    Vidéos : http://vimeopro.com/appcelerator/forging-titanium

    Cours vidéo : http://vimeopro.com/appcelerator/building-native-mobile-applications

    Exemples :

    KitchenSink http://github.com/appcelerator/KitchenSink

    Application multiplateformes : https://github.com/appcelerator/Codestrong

    View Slide

  35. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    35
    Tests unitaires et qualité
    ■ Objectifs :
    ■ Tester certaines parties de l'application automatiquement
    ■ Mettre en place des tests automatiques réguliers
    ■ Améliorer la qualité
    ■ Détecter et corriger les problèmes en avance
    ■ Plusieurs solutions possibles
    ■ Titanium Jasmise -
    https://github.com/guilhermechapiewski/titanium-jasmine
    ■ JsUnity – http://jsunity.com
    ■ Qunit pour Titanium - http://github.com/lukaso/qunit

    View Slide

  36. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    36
    Tests unitaires et qualité

    Utilisation de Titanium jasmine

    Exemple : utilisé pour tester joli.js

    Principe : assertions (expect()) et
    vérifications (toBe())

    Bien mais pas aussi puissant qu'un PHPUnit...
    (function() {
    describe('joli.query', function() {
    var q;
    it('joli.query.destroy()', function() {
    q = new joli.query().destroy().from('human');
    expect(q.getQuery()).toBe('delete from human');
    });
    });
    })();

    View Slide

  37. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    37
    Sommaire
    1. Pourquoi Titanium mobile ?
    2. Qu'est-ce que Titanium mobile ?
    ■ Mode de fonctionnement
    ■ Principes de développement
    3. Démarrer avec Titanium
    ■ Outillage et Documentation
    4. Tour des APIs disponibles
    5. Démonstration simple

    View Slide

  38. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    38
    Gestion des fenêtres

    View Slide

  39. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    39
    Vues
    ■ La composition graphique se fait avec des vues :
    ■ Image view
    ■ Scroll view
    ■ Scrollable view
    ■ Table view
    ■ Web view
    ■ Map view
    ■ Coverflow view
    ■ Dashboard view
    ■ Une vue peut en contenir une autre
    ■ Analogie à Swing...

    View Slide

  40. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    40
    Image view
    Insertion d'images
    ■ Le paramètre « image » peut être
    une url
    var win = Titanium.UI.currentWindow;
    var imageView = Titanium.UI.createImageView({
    image: 'titanium.png',
    width: 261,
    height: 178,
    top: 20
    });
    imageView.addEventListener('load', function()
    {
    Ti.API.info('LOAD CALLED');
    });
    win.add(imageView);

    View Slide

  41. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    41
    Table view
    ■ Données tabulaires
    ■ Possibilité de headers
    ■ Chaque cellule peut contenir des contrôles
    var data = [
    {title: 'Alan', hasChild: true, header: 'A'},
    {title: 'Alice', hasDetail: true},
    {title: 'Brad', header: 'B'},
    {title: 'Brenda'},
    {title: 'Callie', header: 'C'},
    {title: 'Chris'},
    ];
    var search = Titanium.UI.createSearchBar({
    showCancel: false
    });
    // create table view
    var tableview = Titanium.UI.createTableView({
    data: data,
    search: search,
    filterAttribute: 'title'
    });
    win.add(tableview);

    View Slide

  42. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    42
    Widgets
    Les éléments d'interface avec lesquels l'utilisateur
    peut interagir :
    Activity Indicator
    (Date) picker
    Progress bar
    Search bar
    Button bar
    Textarea
    Label
    Slider
    Switch
    Button
    Toolbar
    Textfield

    View Slide

  43. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    43
    Widgets

    View Slide

  44. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    44
    Widgets
    ■ Construction par appel du constructeur dans Ti.UI
    ■ Paramètres nombreux et variés
    ■ API permettant de manipuler les widgets
    ■ Interactions associées à des évènements
    ■ click
    ■ swipe
    ■ touchend
    ■ etc.

    View Slide

  45. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    45
    APIs matérielles
    Titanium donne accès à un grand nombre d'APIs natives de l'appareil :

    Accéléromètre

    Caméra

    Médias

    Géolocalisation

    Réseau

    Base de données

    Presse papier

    etc.
    Toutes ces APIs sont exposées sous Titanium.*

    Exploitables en javascript

    Exploitables depuis les Webview depuis du HTML local

    View Slide

  46. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    46

    View Slide

  47. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    47
    Exemple : Titanium.Media
    ■ accès aux interactions de type « Média »
    ■ Enregistrement / lecture de photos et vidéos
    ■ Enregistrement / lecture de sons ou de morceaux de musique
    ■ Caméra :
    ■ que sur un vrai device, pas en simulateur
    ■ showCamera()
    ■ callbacks
    ■ mediaTypes
    ■ SaveToPhotoGallery
    ■ takePicture()
    ■ hideCamera()
    ■ allowEditing
    ■ showControls
    ■ Overlay
    ■ saveToPhotoGallery()

    View Slide

  48. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    48
    Exemple : Titanium.Media
    var win = Titanium.UI.currentWindow;
    Titanium.Media.showCamera({
    success: function(event) {
    var image = event.media;
    if (event.mediaType == Ti.Media.MEDIA_TYPE_PHOTO) {
    var imageView = Ti.UI.createImageView({
    width: win.width,
    height: win.height,
    image: event.media
    });
    win.add(imageView);
    } else {
    alert('Take a picture. Illegal type ' + event.mediaType);
    }
    },
    cancel: function() {},
    error: function(error) {
    // show an error message
    // test error code Titanium.Media.NO_CAMERA
    },
    saveToPhotoGallery: true,
    mediaTypes: [Ti.Media.MEDIA_TYPE_VIDEO, Ti.Media.MEDIA_TYPE_PHOTO]
    });

    View Slide

  49. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    49
    Organiser son application
    ■ Ne faites pas des fichiers de 1500 lignes !
    ■ Utilisez Titanium.include() (ou require())
    ■ Concevez des modules js
    ■ Pseudo-MVC possible
    ■ Logique métier dans “contrôleur”
    ■ Affichage dans un fichier de vue
    ■ ORMs existants (joli.js FTW – voir
    https://github.com/xavierlacot/joli.js)
    Si vous n'êtes pas méticuleux, vous irez dans le mur

    View Slide

  50. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    50
    Sommaire
    1. Pourquoi Titanium mobile ?
    2. Qu'est-ce que Titanium mobile ?
    ■ Mode de fonctionnement
    ■ Principes de développement
    3. Démarrer avec Titanium
    ■ Outillage et Documentation
    4. Tour des APIs disponibles
    5. Démonstration simple

    View Slide

  51. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    51
    Du temps pour une démo ?
    ■ Un carnet d'adresses
    synchronisé par des Web
    Services
    ■ Le code source est
    disponible sur
    https://github.com/xavierlacot/joli.api.js-app-demo

    View Slide

  52. Paris Android User Group - Développement Cross-Platform avec Titanium Mobile
    Xavier Lacot | 6 Décembre 2011
    52
    STOP WHINING
    MORRON
    GO USE
    TITANIUM
    STOP WHINING
    MORRON
    GO USE
    TITANIUM
    STOP WHINING
    MORRON
    GO USE
    TITANIUM
    STOP WHINING
    MORRON
    GO USE
    TITANIUM
    STOP WHINING
    MORRON
    GO USE
    TITANIUM
    STOP WHINING
    MORRON
    GO USE
    TITANIUM
    STOP WHINING
    MORRON
    GO USE
    TITANIUM
    STOP WHINING
    MORRON
    GO USE
    TITANIUM
    STOP WHINING
    MORRON
    GO USE
    TITANIUM
    STOP WHINING
    MORRON
    GO USE
    TITANIUM

    View Slide

  53. ?
    Des
    questions ?

    View Slide

  54. View Slide