Bonjour à tous,

J'éprouve des difficultés avec l'utilisation des librairies. Voici ce que je désire faire :

J'ai développé un grand nombre de petits composants que j'utilise dans toutes mes applications. Plutôt que de les recopier d'un projet à l'autre (ce qui est une très mauvaise pratique), je me dis qu'il serait souhaitable de les rassembler au sein d'une librairie. Cette librairie de composants serait partagée entre toutes mes applications. Bref, il s'agit de la "raison d'être" d'une librairie...

J'ai donc créé un projet de type "Flex Library Project". Je l'ai nommé "frmawork".

Dans ce projet, j'ai déposé le code d'un de mes composants. Pour commencer, je teste "la manipulation" avec un seul composant. Le nombre de composants dans la librairie n'a pas d'importance.

Le schéma ci-dessous montre l'arborescence du projet.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
 
framework
|-- bin
|   `-- framework.swc
`-- src
    |-- components
    |   `-- UIComponents
    |       `-- DateTimeChooser.as
    `-- interfaces
        |-- IGhostInterface.as
        `-- ISelectorInterface.as
Ce projet compile dans erreur, ni avertissement. La librairie "framework.swc" est créée dans le répertoire "bin".

Je fournis à la fin de ce document le code du composant "DateTimeChooser.as". Afin de tester cette librairie, j'ai créé un projet de type "Application". Il porte le nom "framework-testing". L'arborescence du projet est donnée ci-dessous :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
 
framework-testing
|-- html-template
|   |-- AC_OETags.js
|   |-- history
|   |   |-- history.css
|   |   |-- history.js
|   |   `-- historyFrame.html
|   |-- index.template.html
|   `-- playerProductInstall.swf
|-- libs
`-- src
    `-- DateTimeChooser.mxml
Je fournis à la fin de ce document le code de l'application. L'application compile dans erreur, ni avertissement. Cela dit, la phase d'initialisation de l'application ne se déroule pas normalement:

  • Le composant "n'apparaît pas".
  • L'application "n'en finit pas" de s'initialiser.
  • Une trace montre que la fonction exécutée lors de la levée de l'événement "creationComplete" s'exécute "en boucle". Autrement dit, cet évènement semble être lancé un nombre infini de fois.


Note : La classe "DateTimeChooser" ne pose pas de problème. Si je la teste sans l'inclure dans une librairie, le composant qu'elle implémente se comporte bien.

Je sèche... J'ai vérifié les propriétés du projet "fremawork-testing". En particulier, j'ai vérifié le chemin vers la librairie...

Avez-vous une idée?

Merci,

Denis

Pour information

DateTimeChooser.as

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
 
package components.UIComponents
{
   import flash.events.Event;
 
   import interfaces.IGhostInterface;
   import interfaces.ISelectorInterface;
 
   import mx.containers.HBox;
   import mx.controls.DateField;
   import mx.controls.NumericStepper;
   import mx.controls.Spacer;
   import mx.controls.Text;
   import mx.events.CalendarLayoutChangeEvent;
   import mx.events.NumericStepperEvent;
 
   /** Cette classe implémente un composant utilisé pour sélectionner une date et une heure.
    */
 
   public class DateTimeChooser extends HBox implements IGhostInterface, ISelectorInterface
   {
      private var __pickerDisplay:Text           = new Text();
      private var __language:String              = new String();
      private var __enabled:Boolean              = new Boolean();
      private var __dateFrom:Date                = null;
      private var __dateTo:Date                  = null;
      private var __datePicker:DateField         = new DateField();
      private var __hourPicker:NumericStepper    = new NumericStepper();
      private var __minutePicker:NumericStepper  = new NumericStepper();
 
      /** Construit un objet de sélection de la date et de l'heure.
       *  @param enabled Cette valeur détermine l'état initial du composant.
       *         Les valeurs possibles sont :
       *         * true 
       *         * false
       *         Par défaut, le composant est actif.
       *  @param fromDate Objet de type "Date". Cet objet représente la date de "début" du calendrier. La sélection est impossible avant cette date.
       *         Par défaut, cette date n'est pas définie.
       *  @param toDate Objet de type "Date". Cet objet représente la date de "fin" du calendrier. La sélection est impossible après cette date.
       *         Par défaut, cette date n'est pas définie.
       *  @param language Cette chaîne de caractères définit la langue utilisée pour l'affichage de la date.
       *         Les valeurs possibles sont :
       *         * french
       *         * english
       *         La langue utilisée par défaut est l'anglais.
       */
 
      public function DateTimeChooser(enabled:Boolean=true, fromDate:Date=null, toDate:Date=null, language:String='english')
      {
         super();
         __language = language;
         __enabled  = enabled;
         __dateFrom = fromDate;
         __dateTo   = toDate;
         __createTimeChooser();
         __datePicker.addEventListener(CalendarLayoutChangeEvent.CHANGE,  __dateUpdated);
         __hourPicker.addEventListener(NumericStepperEvent.CHANGE,        __updateDisplay);
         __minutePicker.addEventListener(NumericStepperEvent.CHANGE,      __updateDisplay);
      }
 
      /** Crée le composant utilisé pour sélectionner une heure.
       */
 
      private function __createTimeChooser():void
      {
         var hourMinuteSeparator:Text      = new Text();
         var pickerDisplaySeparator:Spacer = new Spacer();
 
         // Configuration du calendrier.
         __datePicker.yearNavigationEnabled       = false;
         __datePicker.showToday                   = true;
         if (__language == 'french')
         {
            __datePicker.dayNames   = new Array('D', 'L', 'M', 'M', 'J', 'V', 'S');
            __datePicker.monthNames = new Array('Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre');
         }
         if (! __enabled) { __datePicker.enabled  = false; }
         if (__dateFrom != null) { __datePicker.disabledRanges = [ {rangeEnd: __dateFrom} ]; }
         if (__dateTo   != null) { __datePicker.disabledRanges.push({rangeStart: __dateTo}); }
 
         // Définition des contraintes d'utilisation des sélecteurs numériques.
         __hourPicker.minimum       = 0;
         __hourPicker.maximum       = 23;
         __minutePicker.minimum     = 0;
         __minutePicker.maximum     = 59;
 
         // Séparateur entre le composant de sélection de l'heure et celui de sélection des minutes.
         hourMinuteSeparator.htmlText = "<b>:</b>";
         hourMinuteSeparator.width    = 10;
         hourMinuteSeparator.setStyle("textAlign", "center");
         hourMinuteSeparator.setStyle("fontSize", "12");
 
         // Séparateur entre le composant de sélection des minutes et le panneau d'affichage.
         pickerDisplaySeparator.width         = 0;
         pickerDisplaySeparator.percentHeight = 100;
 
         // Panneau d'affichage.
         __pickerDisplay.width         = 60;
         __pickerDisplay.htmlText      = '<b>00:00</b>';
         __pickerDisplay.setStyle("textAlign", "center");
         __pickerDisplay.setStyle("fontSize", "12");
 
         // Assemblage         
         this.horizontalScrollPolicy = "off";
         this.verticalScrollPolicy   = "off";
         this.setStyle("verticalAlign", "middle");
         this.addChild(__datePicker);
         this.addChild(__hourPicker);
         this.addChild(hourMinuteSeparator);
         this.addChild(__minutePicker);
         this.addChild(pickerDisplaySeparator);
         this.addChild(__pickerDisplay);
 
         trace ('DateTimeChosser() done');
      }
 
      /** Cette méthode rend le composant éligible à la destruction.
       */
 
      public function destroy():void
      {
         __datePicker.removeEventListener(CalendarLayoutChangeEvent.CHANGE, __dateUpdated);
         __hourPicker.removeEventListener(NumericStepperEvent.CHANGE,       __updateDisplay);
         __minutePicker.removeEventListener(NumericStepperEvent.CHANGE,     __updateDisplay);
      }
 
      /** Cette méthode renvoie les valeurs sélectionnées par l'utilisateur.
       *  @return La méthode renvoie un objet qui contient deux propriétés :
       *          * hour
       *          * minute
       */
 
      public function getSelectedValues():Object
      {
         var values:Object = new Object();
         values['hour']   = __hourPicker.value;
         values['minute'] = __minutePicker.value;
         return values;
      }
 
      /** Cette méthode permet d'initialiser un composant de sélection avec des valeurs.
       *  @param inValues Cet objet contient les valeurs utilisées pour l'initialisation du composant.
       *         L'objet passé en argument de la méthode doit contenir les propriétés suivantes :
       *         * hour
       *         * minute 
       */
 
      public function setValues(inValues:Object):void
      {
         __hourPicker.value   = inValues['hour'];
         __minutePicker.value = inValues['minute'];
      }
 
      /** Ce gestionnaire d'évènement est exécuté lorsque la valeur d'un des composants "NumericStepper" change.
       * 
       * @param event Évènement envoyé lorsque la valeur d'un des composants "NumericStepper" change.
       */
 
      private function __updateDisplay(event:Event):void
      {
         __pickerDisplay.htmlText = '<b>' + __numberToValue(__hourPicker.value) + ':' + __numberToValue(__minutePicker.value) + '</b>';
      }
 
      /** Ce gestionnaire d'évènement est exécuté lorsque la valeur du composant "DateField" change.
       * 
       * @param event Évènement envoyé lorsque la valeur du composant "DateField" change.
       */
 
      private function __dateUpdated(event:Event):void
      {
 
      }
 
      /** Retourne une chaîne de caractères qui représente l'heure, ou les minutes, sur deux caractères.
       * 
       * @param n Nombre entier qui représente l'heure ou les minutes.
       */
 
      private function __numberToValue(n:Number):String
      {
         if (n < 10) { return '0' + n.toString(); }
         return n.toString();
      }
   }
}
DateTimeChooser.mxml

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
            creationComplete="init()"
            width="100%"
            layout="horizontal">
 
   <mx:Script>
      <![CDATA[
 
         import components.UIComponents.DateTimeChooser;
 
         private var __picker:DateTimeChooser = null;
 
         private function init():void
         {
            trace ('init()');
            __picker = new DateTimeChooser();
            this.addChild(__picker);
         }
 
      ]]>
   </mx:Script>
 
</mx:Application>
IGhostInterface

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
package interfaces
{
	/** Cette interface définit les composants de type "Ghost".
	 * Ces composants sont susceptibles d'être détruits au cours de l'utilisation de l'application.
	 * Ils présentent tous une méthode destinée à libérer les ressources allouées par le composant.
	 */
 
	public interface IGhostInterface
	{
		/** Cette méthode libère les ressources allouées au composant.
		 */
 
		function destroy():void;
	}
}
ISelectorInterface

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 
package interfaces
{
	/** Cette interface définit les composants de type "Selector".
	 *  Ce type de composant est utilisé pour sélectionner des valeurs.
	 *  Il peut aussi être initialisé à des valeurs de départ.
	 */
 
	public interface ISelectorInterface
	{
		/** Cette méthode renvoie les valeurs sélectionnées par l'utilisateur.
		 *  L'organisation de l'objet renvoyé dépend de la nature des informations sélectionnées.
		 */
 
		function getSelectedValues():Object;
 
		/** Cette méthode permet d'initialiser un composant de sélection avec des valeurs.
		 *  @param inValues Cet objet contient les valeurs utilisées pour l'initialisation du composant.
		 */
 
		function setValues(inValues:Object):void;
	}
}