menu
  Home  ==>  articles  ==>  firemonkey  ==>  firemonkey_animations   

Animations FireMonkey - John COLIBRI.


1 - Les Animations FireMonkey Delphi XE2

FireMonkey est la nouvelle librairie Delphi XE2 qui affiche graphiquement les contrôles visuels (boutons, edits etc) avec la possibilité de créer, en Win32, des applications pour Windows 32 et 64, Mac OsX et iOs (iPhone, iPad etc)

Nous avons déjà présenté les Styles FireMonkey, en insistant que ces styles sont bien plus qu'un habillage visuel comme des skins ou des thèmes. Les styles FireMonkey sont au coeur de la représentation graphique des contrôles multi-plateforme. Un contrôle est composés de plusieurs éléments (par exemple, pour un tButton, un tLayout, un tRectangle, un tText et ... des tAnimations). Voici les éléments d'un simple bouton:

tbutton_style



Les Animation permettent de modifier les paramètres de position des contrôles à l'écran (X, Y, rotation, échelle ...), ainsi que les couleurs.




2 - La première animation FireMonkey

La première Animation FireMonkey

2.1 - Déplacer un tButton à l'écran

Pour animer la position X d'un tButton
   lancez Delphi XE2

start_delph_xe2_

   créez une application FireMonkey 2D par

start_firemonkey_hd_app

   dans la Tool Palette, sélectionnez un tButton et posez le sur la Forme

   de l'onglet "Animations" de la Tool Palette, sélectionnez "Animations | tFloatAnimation"

tool_palette_animations

   cliquez sur Button1 pour poser cette tFloatAnimation SUR Button1.

   la FloatAnimation1 n'est pas représentée sur la Forme, mais elle apparaît comme un élément fils de Button1 dans le paneau Structure, en haut à gauche:

floatanimation_in_structure_pane

Si Button1 n'était pas séléctionné lorsque vous déposez FloatAnimation, l'animation sera un fils de la Forme, et c'est celle ci qui sera animée. Dans ce cas:
   sélectionnez FloatAnimation1 dans le paneau de structure et tirez-glissez la SUR Button1



Nous modifions à présent les propriétés de FloatAnimation dans l'Inspecteur d'Objet:

tfloatanimation_properties

Pour déplacer Button1 horizontalement avec des aller-retours:
   sélectionnez PropertyName
   l'Inspecteur d'Objet présente toutes les propriétés de Button1 que FloatAnimation peut modifier:

tfloatanimation_propertyname

   sélectionnez Position.X

   sélectionnez la position maximale qui déterminera quand le déplacement s'arrêtera, par exemple 200

   cliquez Loop pour répéter l'animation

   cliquez Enabled pour lancer l'animation dès le lancement de l'.EXE

   compilez et exécutez

   Button1 se déplace de la position 0 (StartValue, valeur par défaut) à 200
Notez que

  • les positions des contrôles sont définies par Position.X et Position.Y (et non plus par Left et Top), qui sont des réels pour conserver la précision lors des transformations graphiques
  • c'est pourquoi nous avons utilisé un tFloatAnimation
  • nous avons ajouté l'événement FloatAnimation1.OnProcess qui permet d'afficher la position du bouton à chaque itération
  • nous avons aussi ralenti la vitesse en donnant à FloatAnimation1.Duration la valeur 2, puis 10


Pour effectuer une animation, les propriétés nécessaires sont
  • le contrôle dont l'animation est le fils. Attention, par défaut, le "drag and drop" depuis la Tool Palette posera l'animation sur la Forme. Il faudra alors utiliser le Structure Pane pour nicher l'animation dans son contrôle parent. Le mieux est d'utiliser le "clic sur la Tool Panel, clac sur le contrôle parent"
  • PropertyName : c'est la valeur qui sera modifiée de l'animation. Nous avons utilisé Button1.Position.X. Nous aurions pu prendre Y, ou Width. Et pour effectuer des animations en 2D ou plus, il faut déposer autant de composants animation que de valeurs à animer. Pour déplacer notre bouton horizontalement et verticalement en l'élargissant, il aurait fallu ajouter 2 autres tFloatAnimation
  • des valeurs initiales et finales, qui sont gouvernées par StartValue, StopValue et / ou StartFromCurrent


Voyons à présent les principales propriétés de tFloatAnimation



2.2 - tFloatAnimation.Inverse

Dans notre cas, Button1 va de StartValue (0) vers StopValue (200).

Si nous basculons Inverse à True, le bouton se déplace de 200 vers 0

tfloatanimation_inverse



2.3 - tFloatAnimation.Enabled, StartValue, StopValue

Le basculement de Enabled à False, arrête l'animation ET donne à la position la valeur de StopValue (100 dans notre figure) . Le redémarrage se fait par le basculement de Enabled à True, et la valeur de la position redémarre à StartValue

tfloatanimation_enabled



Si nous basculons StartFromCurrent, l'animation démarre à partir de Button1.Position.X:

tfloatanimation_startfromcurrent

au lieu de commencer à Startvalue :

tfloatanimation_start_at_startposition



Notez :

  • il y a un léger décalage entre les positions de démarrage de l'animation et l'affichage, mais cela est peut être du au moment où OnProcess est appelé


2.4 - Enabled, Start(), Stop()

La propriété Enabled permet de lancer ou arrêter les animations. Start() et Stop() sont les méthodes sous-jacentes



2.5 - Duration et Delay

Duration spécifie la durée (en secondes) pour aller de StartValue à StopValue. Cette propriété permet donc de régler la vitesse de l'animation

Delay permet de retarder le démarrage de l'animation



2.6 - Interpolation et AnimationType

L'animation permet donc de faire varier une propriété en fonction du temps. La loi de changement peut être de plusieurs natures
  • linéaire
  • exponentielle
  • sinusoidale
  • élastique
C'est la propriété Interpolation qui détermine cette loi.

Pour les lois qui ne sont pas symmétriques, c'est AnimationType qui indique dans quel sens la loi est exécutée. Prenons le cas d'une animation élastique (semblable à une sinusoide amortie). Nous pouvons avoir les grandes oscillations au début ou à la fin. Ce qui correspond aux différentes valeurs de AnimationType

  • atIn débute par une faible oscillation qui croît
  • atOut débute par une grande oscillation qui s'amenuise
  • atInOut débute par une petite oscillation, puis un mouvement ample au milieu, et un decrescendo vers la fin
Pour se rendre compte de ces possibilités, voici une application où nous pouvons choisir les valeurs de Interpolation et AnimationType. Pour cela nous allons animer les valeurs X et Y d'un tRectangle
  • en conservant une loi linéaire pour X
  • en choisissant dans deux tListBox la loi et le sens de Y
Le mouvement sera donc uniforme de la gauche vers la droite, mais uniforme, ou exponentiel ou sinusoidal etc en Y.

Voici l'application :
   créez une nouvelle application FireMonkey
   posez deux tListBox sur le Forme
   posez un tButton sur la Forme et initialisez par code le contenu de ces tListBox avec les valeurs possibles de tInterpolation et tAnimationType par le clic du bouton

Uses TypInfo;

Function f_interpolation_type_name(p_interpolation_typetInterpolationType): String;
  Begin
    Result:= GetEnumName(TypeInfo(TInterpolationType), Integer(p_interpolation_type));
  End// f_interpolation_type_name

Function f_animation_type_name(p_animation_typetAnimationType): String;
  Begin
    Result:= GetEnumName(TypeInfo(TanimationType), Integer(p_animation_type));
  End// f_animation_type_name

Procedure TForm1.initialize_Click(SenderTObject);
  Var l_interpolation_typetInterpolationType;
      l_animation_typetAnimationType;
  Begin
    // -- fill the interpolation and animation type listboxes
    For l_interpolation_type := Low(TInterpolationTypeTo High(TInterpolationTypeDo
      interpolation_listbox_.Items.AddObject(f_interpolation_type_name(l_interpolation_type),
          TObject(l_interpolation_type));
    interpolation_listbox_.ItemIndex := 0;

    For l_animation_type := Low(TanimationTypeTo High(TanimationTypeDo
      animation_listbox_.Items.AddObject(f_animation_type_name(l_animation_type),
          TObject(l_animation_type));
    animation_listbox_.ItemIndex := 0;
  End// initialize_CLick

   de l'onglet Shape, posez un tRectangle sur la Forme
   de l'onglet Animation, sélectionnez un tFloatAnimation et cliquez sur Rectangle1 pour la poser sur ce rectangle. Faites de même pour la second animation
   pour varier, initialisez ces deux animation par code (il serait possible de tout définir dans l'Inspecteur d'Objet)

Procedure TForm1.initialize_Click(SenderTObject);
  Begin
    ooo

    // -- Attach the FloatAnimations to the Rectangle's position
    With FloatAnimation1 Do
    Begin
      Parent := Rectangle1// already done
      PropertyName := 'Position.X';
      StartValue:= Rectangle1.Position.X;
      StopValue := Rectangle1.Position.X + 200;
      Duration := 5;
      AnimationType := tAnimationType.atIn;
      Interpolation := tInterpolationType.itLinear;
    End;

    With FloatAnimation2 Do
    Begin
      Parent := Rectangle1;
      PropertyName := 'Position.Y';
      StartValue:= Rectangle1.Position.Y;
      StopValue := Rectangle1.Position.Y - 200;
      Duration := 5;
      AnimationType := tAnimationType.atIn;
      Interpolation := tInterpolationType.itLinear;
    End;
  End// initialize_CLick

   posez un bouton "animate_" qui va démarrer les animations, avec les valeurs sélectionnées dans les listbox:

Procedure TForm1.move_Click(SenderTObject);
  Var l_animation_typeTAnimationType;
      l_interpolation_typeTInterpolationType;
  Begin
    With animation_listbox_ Do
      l_animation_type := TAnimationType(Integer(Items.Objects[ItemIndex]));
    FloatAnimation2.AnimationType := l_animation_type;

    With interpolation_listbox_ Do
      l_interpolation_type := TInterpolationType(Integer(Items.Objects[ItemIndex]));
    FloatAnimation2.Interpolation := l_interpolation_type;

    FloatAnimation1.Start;
    FloatAnimation2.Start;
  End// move_Click

   compilez et exécutez

   cliquez "initialize_" pour remplir les deux listbox
   sélectionnez par exemple "itElastic" et "atIn"
   cliquez "animate_"
   le rectangle se déplace vers la droite en oscillant de plus en plus fort verticalement

   sélectionnez "atOut"
   le rectangle oscille fortement verticalement, et ces oscillations diminuent


Notez que

  • expliquer des animations par du texte et des images statiques relève du paradoxe.
  • le mieux serait de dessiner la trajectoire suivi par le tRectangle. Nous n'y sommes pas arrivés
    • l'aide Delphi, dont est tiré cet exemple, contient des notations erronnées (les énumérés d'interpolation correspondent à des identificateurs de la beta test avant des changements de noms effectués mi Août)
    • le code pour tracer devrait utiliser:
      • l'initialisation de la brosse employée pour tirer les traits

        Canvas.Stroke.Color := tAlphaColor.Red;
        Canvas.Stroke.Kind:= tBrushKind.bkSolid;

      • le tracé entre la position courante et la position précédente dans l'événement OnProcess de l'une des animations :

        Var g_previous_positiontPointF;

        Procedure TForm1.FloatAnimation1Process(SenderTObject);
          Var l_current_positiontPointF;
          Begin
            l_current_position.X := Rectangle1.Position.X;
            l_current_position.Y := Rectangle1.Position.Y;

            Canvas.DrawLine(l_current_positiong_previous_position, 1.0);

            g_pevious_position:= l_current_position;
          End// FloatAnimation1Process


    Nous n'avons jamais pu le faire fonctionner. De plus, la moindre faute de syntaxe a zappé Delphi XE2. Nous l'avons rechargé une cinquantaine de fois, sans amélioration. Il est probable que nous avons un problème de hard sur ce PC que nous utilisons depuis début Septembre. Ou alors nous avons réussi a "animer le crash de XE2" !

  • l'exemple sans tracé de la trajectoire fonctionne néanmoins


Plus intéressant, notez
  • la notation totalement qualifiée des énumérés, que nous avions déjà rencontré dans notre article sur les styles:
    • tInterpolation est défini dans FMX.TYPES par:

      Type TInterpolationType = (itLinearitQuadraticitCubic
          itQuarticitQuinticitSinusoidalitExponentialitCircular,
          itElasticitBackitBounce

    • pour attribuer une valeur, nous utilisons

      FloatAnimation1.Interpolation := tInterpolationType.itLinear;

  • le changement des propriétés par rapport à la VCL (Fill et Stroke pour le dessin, Position pour la position etc)

  • le changement des unités (tBrush se trouve dans FMX.TYPES, et pas dans GRAPHICS)


2.7 - Trigger et TriggerInverse

Ces propriétés permettent de démarrer une animation en fonction d'un événement. Par exemple lorsque la souris arrive au dessus d'un contrôle (

Voici un exemple qui agrandit un tEdit lorsque la souris arrive au dessus du contrôle, et le rétrécit lorsqu'il sort:
   créez une nouvelle application FireMonkey
   posez un tEdit sur la Forme
   poses une tFloatAnimation SUR Edit1, nommez la "enlarge_FloatAnimation" et modifiez les propriétés
  • PropertyName : Width (de Edit1 !)
  • StartValue : 100
  • StopValue : 160
  • Trigger : "IsMouseOver=true"
   compilez, exécutez, et déplacez la souris SUR Edit1
   voici le résultat:



Nous pouvons aussi retourner aux valeurs initiales, en utilisant InverseTrigger et la valeur inverse:
   sélectionnez InverseTrigger et donnez lui la valeur "IsMouseOver=False"
   compilez, exécutez, et déplacez la souris SUR Edit1 puis en dehors de Edit1
   voici le résultat:

animation_trigger



Nous aurions aussi pu utiliser une seconde tFloatAnimation pour retourner à l'état initial
   copiez / collez Edit1
   poses une autre tFloatAnimation SUR Edit2, nommez la "shrink_FloatAnimation" et modifiez les propriétés
  • PropertyName : Width
  • StartValue : 100
  • StopValue : 160
  • Inverse : True
  • Trigger : "IsMouseOver=false"
   voici le résultat

animation_trigger_triggerinverse



Notez que

  • Trigger et TriggerInverse sont des String
  • les propriétés du parent qui peuvent être utilisées sont:
    • IsMouseOver
    • IsFocused
    • IsVisible
    • IsDragOver
    • IsOpen.
  • la chaîne se note donc, par exemple 'IsDragOver=True'



3 - Animation FireMonkey 3D

Allez, un peu de chiqué pour finir:
   ouvrez une application 3D par "File | New | Other | FireMonkey 3D"
   posez un tText3D sur la Forme
  • donnez une valeur à Text
  • agrandissez Font.Size à 20
   posez une tFloatAnimation sur Text3d1 et initialisez
  • PropertyName : RotationAngle.X
  • StartValue : 0
  • StopValue : 360
  • Enabled : True
  • Loop : True
   posez une source de lumière tLight sur la Forme, éloignez la du centre et dirigez la lumière vers notre texte

animation_3d_text3d_light

   voici un example:

animation_3d_display



Notez que
  • Les "poignées" rectangulaires servent à orienter le composant 3D. En rouge l'une de ces poignées. La poignée cubique en bas à droite sert à dimensionner le composant (pas la lumière qui est de taille fixe)
  • X va du centre de l'écran vers l'est
  • notre Forme comprend aussi le texte 3d de la démo 3D de FireMonkey (avec un Y de 10 qui le rend invisible dans notre image)



4 - Vcl ou FireMonkey ?

4.1 - Stabilité

  • mettez vous en "Tools | Options | Edit AutoSave", comme d'habitude, et sauvegardez vos sources fréquemment. Cave Emptor.
  • actuellement, Delphi XE2 est un peu moins stable que Delphi XE. Cela devrait être inversé avec les prochaines mises à jour


4.2 - Documentation

  • très générale à ce stade
  • les démos sont certainement la meilleure source d'inspiration à ce stade
  • ici aussi les mises à jour sont attendues avec impatience
  • Embarcadéro France devrait organiser plusieurs Workshops FireMonkey. Ceux-ci devraient vous permettre une prise en main plus facile de FireMonkey


4.3 - Vcl ou FireMonkey ?

  • un blog très intéressant a été publié par Julian BUCKNALL de DevX. Plusieurs points en ressortent
    • Embarcadero externalise de plus en plus, notamment en Espagne et en Russie
    • Embarcadéro soutient que la Vcl continuera à se développer. Mais le poids respectifs du développement de chacun dépendra de nous
    • néanmoins de nombreux développeurs "backend" (comptabilité, facturation) doutent, à juste titre, que les comptables se précipitent sur leur iPhone ou même leur iPad pour effectuer leur saisie. Les applications Vcl Win32 ont donc encore de beaux jours devant elles. Quitte à ajouter un peu de "touch" ici ou là
    • et ces développeurs ne se lanceront dans FireMonkey que si des composants comme QuantumGrid ou autre auront franchi le pas
  • en résumé il semble qu'Embarcadéro ait fait un pari énorme sur FireMonkey. Le développement fulgurant des mobiles les y a entraînés. Il reste à fournir une version stable et documentée de cette plateforme.
  • le chef de produit Delphi a promis des mises à jour mensuelles de FireMonkey. Elles seront les bienvenues
  • quoiqu'il en soit, l'effort est celui de la prise en main d'une nouvelle librairie de composants graphiques, ce qu'est bien FireMonkey. Certes les composants non visuels sont les mêmes (bases de données, Indy) etc. Mais il y aura tout de même quelques surprise dans la migration (il faut, par exemple, qualifier le nom des unités)
  • une petite critique finale: la furieuse activité de promotion mondiale de Delphi XE2 fait chaud au coeur, mais la première manipulation déçoit un peu, surtout au niveau de la doc de FireMonkey. D'aucuns affirment qu'une présentation de FireMonkey comme une "première version" de cet outil eut été plus réaliste et sage que comme "l'outil qui vous permettra de placer vos applications dans les mac store demain". Hem. Il est donc impératif que ce produit se consolide et se stabilise.



5 - Télécharger le code source Delphi

Vous pouvez télécharger: Ce .ZIP qui comprend:
  • le .DPR, la forme principale, les formes annexes eventuelles
  • les fichiers de paramètres (le schéma et le batch de création)
  • dans chaque .ZIP, toutes les librairies nécessaires à chaque projet (chaque .ZIP est autonome)
Ces .ZIP, pour les projets en Delphi 6, contiennent des chemins RELATIFS. Par conséquent:
  • créez un répertoire n'importe où sur votre machine
  • placez le .ZIP dans ce répertoire
  • dézippez et les sous-répertoires nécessaires seront créés
  • compilez et exécutez
Ces .ZIP ne modifient pas votre PC (pas de changement de la Base de Registre, de DLL ou autre). Pour supprimer le projet, effacez le répertoire.

La notation utilisée est la notation alsacienne qui consiste à préfixer les identificateurs par la zone de compilation: K_onstant, T_ype, G_lobal, L_ocal, P_arametre, F_unction, C_lasse. Elle est présentée plus en détail dans l'article La Notation Alsacienne



Comme d'habitude:

  • nous vous remercions de nous signaler toute erreur, inexactitude ou problème de téléchargement en envoyant un e-mail à jcolibri@jcolibri.com. Les corrections qui en résulteront pourront aider les prochains lecteurs
  • tous vos commentaires, remarques, questions, critiques, suggestion d'article, ou mentions d'autres sources sur le même sujet seront de même les bienvenus à jcolibri@jcolibri.com.
  • plus simplement, vous pouvez taper (anonymement ou en fournissant votre e-mail pour une réponse) vos commentaires ci-dessus et nous les envoyer en cliquant "envoyer" :
    Nom :
    E-mail :
    Commentaires * :
     

  • et si vous avez apprécié cet article, faites connaître notre site, ajoutez un lien dans vos listes de liens ou citez-nous dans vos blogs ou réponses sur les messageries. C'est très simple: plus nous aurons de visiteurs et de références Google, plus nous écrirons d'articles.



6 - Quelques références

  • Delphi: VCL is dead, long live FireMonkey
      Julian Bucknall (DevExpress) - 19 Sept 2011
    • Vcl vs FireMonkey. Très instructif
  • la doc officielle
    • FireMonkey Application Platform

    • les démos sont téléchargeables (sans avoir nécessairement la version) sur SourceForge (comme les démos 2010 et Delphi XE d'ailleurs):

      Démos Rad Studio XE2

      et

      • soit cliquez sur "Download GNU tarball", sauvegardez le fichier "radstudiodemos-FireMonkey.tar.gz" et décompressez
      • soit utilisez Svn:
           "File / Open From Version Control ..."
           entrez une URL, par exemple:

        https://radstudiodemos.svn.sourceforge.net/svnroot/radstudiodemos/branches/RadStudio_XE2/LiveBindings/

           sélectionnez un répertoire cible, par exemple c:Delphi
        et pour mettre à jour la version
           "Project Manager | sélectionnez le projet | clic droit | Subversion / Update / From Project Directory"

  • nos précédents articles Delphi XE2 :
    •  Présentation Delphi XE2
        John COLIBRI - 18 Août 2011
      • Présentation des informations disponibles sur Delphi XE2 à partir de ce qui était publié sur le Web à cette date.
    • Delphi XE2 - World Tour ParisRésumé de ce que nous avons appris à la conférence "Delphi XE2 World Tour" qui s'est déroulée à Paris le 8 Septembre 2011 - Complément à l'article du 19 Août
    • Les Styles FireMonkey : changer le style d'un objet ou de tous les objets d'une Class, le Style Designer FireMonkey, contenu d'un fichier .STYLE, la propriété StyleLookup, les styles prédéfinis (en anglais).
    • Mise à jour Delphi XE2 1 Tim DelChiaro a annoncé et fourni les liens du téléchargement et de la doc de la première mise à jour Delphi XE2 (28 Septembre 2011).
    • LiveBindings Delphi XE2 : les LiveBindings permettent d'évaluer dynamiquement des expressions entre propriétés de composants source et cible. La définition des relations sous forme de String offre une grande flexibilité et est plus générale que les db_xxx de la VCL. Ces LiveBindings seront surtout utilisée par FireMonkey, en particulier pour les bases de données
    • Architecture LiveBindings Delphi : analyse de l'architecture des LiveBindings Delphi : comment tBindingExpression compile une expression au format String pour contruire un environment qui référence des tObject et évalue cette expressioin pour remplir les propriétés de composants. Affichage du pseudo-code généré. Diagramme de classe UML de l'architecture des LiveBindings
    • Architecture FireMonkey : la hiérarchie tComponent <- tFmxObject <- Fmx.tControl <- tStyledControl. Diagramme de Classe UML avec les principaux composants et explication de l'emplacements des fonctionalités de base (le Canvas, la Souris, le Clavier).
    • Inspecteur d'Objet simple avec FireMonkey : création d'un Inspecteur d'Objet simple, présentant les composants présents sur la Forme et affichant les noms et valeurs de ses propriété, avec modifications possibles des propriétés à l'exécution. Utilisation de la RTTI, version pré et post Delphi 2010



7 - L'auteur

John COLIBRI est passionné par le développement Delphi et les applications de Bases de Données. Il a écrit de nombreux livres et articles, et partage son temps entre le développement de projets (nouveaux projets, maintenance, audit, migration BDE, migration Xe_n, refactoring) pour ses clients, le conseil (composants, architecture, test) et la formation. Son site contient des articles avec code source, ainsi que le programme et le calendrier des stages de formation Delphi, base de données, programmation objet, Services Web, Tcp/Ip et UML qu'il anime personellement tous les mois, à Paris, en province ou sur site client.
Created: jan-04. Last updated: mar-2020 - 250 articles, 620 .ZIP sources, 3303 figures
Contact : John COLIBRI - Tel: 01.42.83.69.36 / 06.87.88.23.91 - email:jcolibri@jcolibri.com
Copyright © J.Colibri   http://www.jcolibri.com - 2001 - 2020
Retour:  Home  Articles  Formations  Développement Delphi  Livres  Pascalissime  Liens  Download
l'Institut Pascal

John COLIBRI

+ Home
  + articles_avec_sources
    + bases_de_donnees
    + web_internet_sockets
    + services_web_
    + prog_objet_composants
    + office_com_automation
    + colibri_utilities
    + uml_design_patterns
    + graphique
    + delphi
    + outils
    + firemonkey
      – firemonkey_animations
      – livebindings_delphi
    + vcl_rtl
    + colibri_helpers
    + colibri_skelettons
    + admin
  + formations
  + developpement_delphi
  + présentations
  + pascalissime
  + livres
  + entre_nous
  – télécharger

contacts
plan_du_site
– chercher :

RSS feed  
Blog

Formation Perfectionnement Delphi Les techniques avancées : la programmation objet, l'écriture de composants, l'accès aux bases de données, Xml, le multi-tâche, la programmation Internet - 5 jours