Premier commit
[powerfractal.git] / CD / Src / Power_Tools.adb
1 ------------------------------------------------------------------------------------------------
2 -- Nom : Power_Tools / fait partie du programme Power Fractal --
3 -- --
4 -- Auteurs : Gregory Burri & Adrien Crivelli --
5 ------------------------------------------------------------------------------------------------
6 -- But : Outils de hauts niveau pour le tracage, le recadrage et le centrage --
7 -- sur la fractal a l'Ecran. --
8 ------------------------------------------------------------------------------------------------
9
10 with Ada.Text_IO; use Ada.Text_IO;
11 with Power_Calculator;
12 with Power_Colors;
13 with Power_Draw; use Power_Draw;
14
15 with Spider;
16 with Spider.Draw;
17 with Spider.User; use Spider.User; --Enfant gerant la souris et le clavier
18
19 with Power_List;
20
21 with Ada.Numerics; use Ada.Numerics;
22 with Ada.Numerics.Generic_Elementary_Functions;
23
24
25 package body Power_Tools is
26
27 ------------------------------------------------------------------------------------------------
28 -- Nom : Dessiner_Fractal --
29 -- But : Dessiner la fracal a l'ecran --
30 -- --
31 -- Parametres ----------------------------------------------------------------------------------
32 -- In : * La fractal a dessiner --
33 -- --
34 ------------------------------------------------------------------------------------------------
35 procedure Dessiner_Fractal (Fractal : in Cara_Fractal; X, Y : Natural := 0;
36 Largeur_Zone : Natural := Largeur_Ecran;
37 Hauteur_Zone : Natural := Hauteur_Ecran) is
38
39 use Power_Calculator;
40 use Power_Colors;
41
42 Degrade : T_Tab_Couleur(1 .. Fractal.Nb_Iteration_Max); --Le deegrade de couleur
43
44
45 -------------------------------------------tests----------------------------------------
46 --2 si la matrice doit etre calcule quatre fois plus grande sinon 1
47 Quadruple : Natural := Boolean'Pos(Fractal.Antialiasing) + 1;
48
49 --les dimensions de la zone de calcul, elles sont double si l'antialiasing est active
50 Largeur_Zone_Anti : Natural := Largeur_Zone * Quadruple + Boolean'Pos(Fractal.Antialiasing);
51 Hauteur_Zone_Anti : Natural := Hauteur_Zone * Quadruple + Boolean'Pos(Fractal.Antialiasing);
52 --
53
54 --La matrice d'iteration
55 Matrice_Iteration : T_Matrice_Iteration (0..Largeur_Zone_Anti, 0..Hauteur_Zone_Anti);
56
57 begin -- Dessiner_Fractal
58
59 New_Line;
60 Put(" Matrix... ");
61
62 --Si la fractal est de type mandelbrot alors
63 if Fractal.Ensemble = Mandelbrot then
64 --Calcul la fractal sur l'ensemble de mandelbrot
65 Matrice_Iteration := Mandel_Gen (Largeur_Zone_Anti, Hauteur_Zone_Anti, Fractal);
66 else --sinon (Julia)
67 --Calcul la fractal sur l'ensemble de julia
68 Matrice_Iteration := Julia_Gen (Largeur_Zone_Anti, Hauteur_Zone_Anti, Fractal);
69 end if;
70
71
72
73 --Si la procedure a ete appelle avec les parametres par defaut
74 if Largeur_Zone = Largeur_Ecran and Hauteur_Zone = Hauteur_Ecran then
75
76 --Si l'antialiasing est active alors
77 if Fractal.Antialiasing then
78 --Utilise la matrice qui fait le quadruple de taille de l'ecran
79 Matrice_Iteration_Global := (True, Matrice_Iteration);
80 else
81 --Utilise la matrice normale
82 Matrice_Iteration_Global := (False, Matrice_Iteration);
83 end if;
84
85 else --sinon (dimension arbitraire)
86
87 --Si l'antialiasing est actif alors
88 if Fractal.Antialiasing then
89
90 --Copie la 'petite' matrice dans la grande globale
91 --Le coin de la petite est au coordonnees xy
92 for I in Matrice_Iteration'range(1) loop
93 for J in Matrice_Iteration'range(2) loop
94
95 --Dessine la sous matrice calcule de la matrice tampon sur l'ecran
96 Matrice_Iteration_Global.Matrice_Iteration_Anti(I + 2 * X, J + 2 * Y)
97 := Matrice_Iteration(I, J);
98
99 end loop;
100 end loop;
101
102 else
103
104 --Copie la 'petite' matrice dans la grande globale
105 --Le coin de la petite est au coordonnees xy
106 for I in Matrice_Iteration'range(1) loop
107 for J in Matrice_Iteration'range(2) loop
108
109 Matrice_Iteration_Global.Matrice_Iteration(I + X, J + Y)
110 := Matrice_Iteration(I, J);
111
112 end loop;
113 end loop;
114 end if;
115 end if;
116
117
118 Put_Line("OK");
119 Put(" Colors... ");
120 Creer_Degrade(Fractal, Degrade, Fractal.Nb_Iteration_Max); --Calcul le degrade
121 Put_Line("OK");
122 Put(" Conversion... ");
123
124
125 --Si l'antialiasing est active alors
126 if Fractal.Antialiasing then
127 --Calcul la matrice de sortie avec antialiasing
128 Matrice_Tampon_Ecran :=Calcul_Antialiasing(Conversion_Couleur
129 (Matrice_Iteration_Global.Matrice_Iteration_Anti, Degrade));
130 else
131 --Calcul la matrice de sortie (sans antialiasing)
132 Matrice_Tampon_Ecran := Conversion_Couleur
133 (Matrice_Iteration_Global.Matrice_Iteration, Degrade);
134 end if;
135
136
137 --Si l'affichage du degrade est actif alors
138 if Fractal.Dessine_Degrade and Largeur_Zone = Largeur_Ecran
139 and Hauteur_Zone = Hauteur_Ecran then
140
141 Affiche_Degrade(Fractal); --Affiche le degrade (dans le tampon)
142
143 end if;
144
145 Put_Line("OK");
146 Put(" Drawing... ");
147
148 -- Parcours chaque colonne de l'ecran
149 for I in Largeur_Zone / 2 + X..Largeur_Zone + X loop
150
151 --Dessine un colonne depuis le tampon a droite du cantre
152 Ligne_Matrice_Vert (Y, Y + Hauteur_Zone, I);
153
154 --Dessine un colonne depuis le tampon a gauche du centre
155 Ligne_Matrice_Vert (Y, Y + Hauteur_Zone, 2 * X - I + Largeur_Zone);
156
157 end loop;
158
159 Put_Line("OK");
160
161 end Dessiner_Fractal;
162
163
164
165 ------------------------------------------------------------------------------------------------
166 -- Nom : Rafraichir_couleur --
167 -- But : Mets a jour les couleur et dessinne la fractal --
168 -- --
169 -- Parametres ----------------------------------------------------------------------------------
170 -- In : * La fractal a dessiner --
171 -- --
172 ------------------------------------------------------------------------------------------------
173 procedure Rafraichir_Couleur (Fractal : in Cara_Fractal) is
174 use Power_Calculator;
175 use Power_Colors;
176 Degrade : T_Tab_Couleur(1 .. Fractal.Nb_Iteration_Max); --Le deegrade de couleur
177 begin -- Rafraichir_Couleur
178 New_Line;
179 Put(" Colors... ");
180 Creer_Degrade(Fractal, Degrade, Fractal.Nb_Iteration_Max); --Calcul le degrade
181 Put_Line("OK");
182 Put(" Conversion... ");
183
184 --Si l'antialiasing est active alors
185 if Fractal.Antialiasing then
186 --Calcul la matrice de sortie avec antialiasing
187 Matrice_Tampon_Ecran := Calcul_Antialiasing
188 (Conversion_Couleur(Matrice_Iteration_Global.Matrice_Iteration_Anti, Degrade));
189 else
190 --Calcul la matrice de sortie (sans antialiasing)
191 Matrice_Tampon_Ecran := Conversion_Couleur
192 (Matrice_Iteration_Global.Matrice_Iteration, Degrade);
193 end if;
194
195 --Si l'affichage du degrade est actif alors
196 if Fractal.Dessine_Degrade then
197 Affiche_Degrade(Fractal); --Affiche le degrade (dans le tampon)
198 end if;
199
200 Put_Line("OK");
201 Put(" Drawing... ");
202
203 -- Parcours chaque colonne de l'ecran
204 for X in Largeur_Ecran / 2..Largeur_Ecran loop
205
206 --Dessine un colonne depuis le tampon a droite du cantre
207 Ligne_Matrice_Vert (0, Hauteur_Ecran, X);
208
209 --Dessine un colonne depuis le tampon a gauche du centre
210 Ligne_Matrice_Vert (0, Hauteur_Ecran, Largeur_Ecran - X);
211
212 end loop;
213
214 Put_Line("OK");
215
216 end Rafraichir_Couleur;
217
218
219 ------------------------------------------------------------------------------------------------
220 -- Nom : Zoom_Souris --
221 -- But : Tracer un cadre a la souris pour zoomer --
222 -- et clic-droit pour dezoomer (recentre au coordonnees de la sourris) -- --
223 -- --
224 -- Parametres ----------------------------------------------------------------------------------
225 -- In : * la fractal sur laquelle zoomer --
226 -- --
227 ------------------------------------------------------------------------------------------------
228 procedure Zoom_Souris(Fractal : in out Cara_Fractal) is
229
230 --La distance [px] entre le haut de la croix et l'arete superieur du cadre de zoom
231 --si cette distance est inferieur a une certaine valeur alors efface la croix, sinon affiche
232 --la croix
233 Distance_Visible : constant := 10 + Rayon_Ext_Croix;
234
235 X1, Y1, --Coordonnees du centre du cadre
236 X2, Y2, --Coordonnees de la souris lors du tracage du cadre
237
238 X2_Avant, Y2_Avant : Integer := 0; --Pour sauvegarder des coordonnees
239 Clic_Droit : Boolean; --Si un clic droit a lieu
240 Clic_Gauche : Boolean; --Si un clic Gauche a lieu
241
242 Clic_Clavier : Boolean; --Si une touche est pressee
243 Touche : Character; --La touche presse
244
245 X1_Float, Y1_Float , --Les coordonnees du centre par rapport au unite reel
246
247 --Les coordonnees du coin inferieur droit ou gauche du cadre de zoom en unite reel
248 X2_Float, Y2_Float : Long_Float;
249
250 --La Largeur et la longueur en float (evite de devoir faire plusieurs fois la convertion
251 Largeur_Zone_Tmp_Float : Long_Float := Long_Float(Largeur_Ecran);
252 Hauteur_Zone_Tmp_Float : Long_Float := Long_Float(Hauteur_Ecran);
253 --
254
255 Pre_Calcul : Long_Float; --Precalcul d'un partie du calcul
256
257 Croix : Boolean; --Pour savoir si la croix est affiche ou non
258
259 begin -- Zoom_Souris
260
261 --Boucle pour pouvoir zoomer ou dezoomer plusieur fois de suite sans taper la commande
262 loop
263
264 --Initialise les flags pour le clavier et la souris
265 Touche := Vide;
266 Clic_Clavier := False;
267 Clic_Droit := False;
268 Clic_Gauche := False;
269 --
270
271 Croix := False; --ne dessine pas la croix
272
273 --Boucle s'executant jusqu'a qu'un clic soit fait ou que la touche ESC soit presses
274 while not Clic_Droit and not Clic_Gauche and not (Clic_Clavier and Touche = Echape) loop
275
276 Right_Clic(X2, Y2, Clic_Droit); --Lorsque un clic-droit arrive
277 Left_Clic(X1, Y1, Clic_Gauche); --Lorsque un clic-gauche arrive
278 Key_Pressed(Touche, Clic_Clavier); --Lorsque une touche est presse
279 Sleep(10); --Redonne la main au systeme pendant 10ms
280
281 end loop;
282
283
284 --Si il y a eu la touche ESC presse alors quitte la procedure
285 if Clic_Clavier and Touche = Echape then
286 return;
287 end if;
288
289 Clic_Clavier := False; --Remet a faux le flag du clavier
290
291 --Si un clic gauche a est effectue
292 if Clic_Gauche then
293
294 Clic_Gauche := False; --Remet a faux le flag du clic gauche
295 Spider.Move_To(X1, Y1); --Lit les coordonnees de la souris
296
297 --Copie des coordonnees de la souris dans XY2
298 X2 := X1;
299 Y2 := Y1;
300
301 --Sauvegarde Les coordonnees XY2
302 X2_Avant := X2;
303 Y2_Avant := Y2;
304
305 --Attends un autre clic-Gauche
306 while not Clic_Gauche loop
307
308 Mouse(X2, Y2); --Lit les coordonnees de la souris
309
310 --Calcul Y2 en fonction de X1 en tenant compte des proportion de la zone de dessin
311 Y2 := Y1 + ((X2-X1) * Hauteur_Ecran / Largeur_Ecran);
312
313 --Si le cadre vient a depasser de l'ecran (impossible a afficher) alors
314 if X2 not in 0..Largeur_Ecran or (-X2 + 2*X1) not in 0..Largeur_Ecran
315 or Y2 not in 0..Hauteur_Ecran or (-Y2 + 2*Y1) not in 0..Hauteur_Ecran then
316
317 --Remets les coordonnes du passage precedant
318 Y2 := Y2_Avant;
319 X2 := X2_Avant;
320 --
321
322 end if;
323
324 --Si le bord superieur est plus bas que la hauteur de la croix + 'Distance_Visible'
325 --et que la croix est affichee alors
326 if Y2 in (Y1 - Distance_Visible)..(Y1 + Distance_Visible) and Croix then
327
328 Efface_Croix(X1, Y1); --Efface la croix
329 Croix := False; --La croix n'est pas affichee
330
331 --Si le bord superieur est plus haut que la hauteur de la croix + 'Distance_Visible'
332 --et que la croix n'est pas affichee alors
333 elsif Y2 not in (Y1 - Distance_Visible)..(Y1 + Distance_Visible) and not Croix then
334
335 Dessin_Croix(X1, Y1); --Efface la croix
336 Croix := True; --La croix est affichee
337
338 end if;
339 ---------------------------------
340
341 --Dessine une boite : avec le point XY1 au centre
342 Boite((-X2 + 2*X1), (-Y2 + 2*Y1), X2, Y2, Couleur_Cadre);
343
344 --Si les lignes verticales du cadre ont bougees
345 --par rapport au passage d'avant alors
346 if X2 /= X2_Avant then
347
348 --Efface les lignes verticales au coordonnees d'avant (XY2_Avant)
349 Ligne_Matrice_Vert((-Y2_Avant + 2*Y1),Y2_Avant, X2_Avant);
350 Ligne_Matrice_Vert((-Y2_Avant + 2*Y1),Y2_Avant, (-X2_Avant + 2*X1));
351
352 end if;
353
354 --Si les lignes horizontales du cadre ont bougees
355 --par rapport au passage d'avant alors
356 if Y2 /= Y2_Avant then
357
358 --Efface les lignes horizontales au coordonnees d'avant (XY2_Avant)
359 Ligne_Matrice_Hori((-X2_Avant + 2*X1),X2_Avant, Y2_Avant);
360 Ligne_Matrice_Hori((-X2_Avant + 2*X1),X2_Avant, (-Y2_Avant + 2*Y1));
361
362 end if;
363
364 Sleep(10); --Redonne la main au system pendant 10ms
365
366 --Sauvegarde les coordonnees courantes
367 X2_Avant := X2;
368 Y2_Avant := Y2;
369 --
370
371 Key_Pressed(Touche, Clic_Clavier); --Lorsqu'une touche est pressee
372
373 --Si la touche ESC est pressee
374 if Clic_Clavier and Touche = Echape then
375
376
377 --Efface le cadre
378 Ligne_Matrice_Hori((-X2 + 2*X1),X2, Y2);
379 Ligne_Matrice_Hori((-X2 + 2*X1),X2, (-Y2 + 2 * Y1));
380
381 Ligne_Matrice_Vert((-Y2 + 2*Y1),Y2, X2);
382 Ligne_Matrice_Vert((-Y2 + 2*Y1),Y2, (-X2 + 2 * X1));
383 --
384
385 --Si la croix est presente a l'ecran alors l'efface
386 if Croix then
387 Efface_Croix(X1, Y1);
388 end if;
389
390 return; --Sort de la procedure
391 end if;
392
393 Left_Clic(X2, Y2, Clic_Gauche); --Lorsque un clic-gauche arrive
394
395 end loop;
396
397 --Les coordonnees XY1 sont ajuste au coin superieur droit au gauche
398 X1 := (-X2 + 2 * X1);
399 Y1 := (-Y2 + 2 * Y1);
400
401 --Si la largeur du cadre est nulle alors reajuste X1
402 if X1 = X2 then
403 X1 := X1 + 1;
404 end if;
405
406 --Si la largeur du cadre est nulle alors reajuste X1
407 if Y1 = Y2 then
408 Y1 := Y1 + 1;
409 end if;
410
411 end if;
412
413 Pre_Calcul := (2.0 * Largeur_Zone_Tmp_Float) * Fractal.Zoom;
414
415 --Convertie la valeur X2 du point a l'ecran(pixel) en valeur reel sur la fractal
416 --Voir la doc pour plus d'informations
417 X2_Float := ( (Long_Float(X2) / Largeur_Zone_Tmp_Float) - 0.5 )
418 / Fractal.Zoom + Fractal.Centre.X ;
419
420 --Convertie la valeur Y2 du point a l'ecran(pixel) en valeur reel sur la fractal
421 --Voir la doc pour plus d'informations
422 Y2_Float := (-2.0 * Long_Float(Y2) + Hauteur_Zone_Tmp_Float)
423 / Pre_Calcul + Fractal.Centre.Y; -- de 0 a 1
424
425 --Corrige les valeurs par rapport a l'angle (fractal.angle)
426 Power_Calculator.Change_Angle(X2_Float, Y2_Float, Fractal);
427
428
429 --Si le bouton droit de la souris a ete presse => dezoom
430 if Clic_Droit then
431
432 --Ajuste le centre de la fractal a l'endroit clique
433 Fractal.Centre.X := X2_Float;
434 Fractal.Centre.Y := Y2_Float;
435
436 --Si le nouveau zoom n'est pas inferieur a la limte alors
437 if Fractal.Zoom / Facteur_Zout >= Zoom_Min then
438 --Calcul le nouveau zoom
439 Fractal.Zoom := Fractal.Zoom / Facteur_Zout;
440 else --si il depasse la limite
441 Fractal.Zoom := Zoom_Min; --le remene au zoom minimum
442 end if;
443
444 else --sinon (c'est le bouton de gauche qui a ete presse)
445
446 --Convertie la valeur X2 du point a l'ecran(pixel) en valeur reel sur la fractal
447 --Voir la doc pour plus d'informations
448 X1_Float := ( (Long_Float(X1) / Largeur_Zone_Tmp_Float) - 0.5 )
449 / Fractal.Zoom + Fractal.Centre.X ;
450
451 --Convertie la valeur Y1 du point a l'ecran(pixel) en valeur reel sur la fractal
452 --Voir la doc pour plus d'informations
453 Y1_Float := (-2.0 * Long_Float(Y1) + Hauteur_Zone_Tmp_Float)
454 / Pre_Calcul + Fractal.Centre.Y;
455
456 --Corrige les valeurs par rapport a l'angle (fractal.angle)
457 Power_Calculator.Change_Angle(X1_Float, Y1_Float, Fractal);
458
459 --Le nouveau zoom est egal au rapport entre la fenetre total est le cadre trace
460 Fractal.Zoom := Fractal.Zoom * abs(Largeur_Zone_Tmp_Float / Long_Float(X2 - X1));
461
462 --Le centre est egal au centre du cadre
463 Fractal.Centre.X := (X1_Float + X2_Float) / 2.0;
464 Fractal.Centre.Y := (Y1_Float + Y2_Float) / 2.0;
465 end if;
466
467 Dessiner_Fractal(Fractal); --Dessine la fractale
468
469 end loop;
470
471 end Zoom_Souris;
472
473 ------------------------------------------------------------------------------------------------
474 -- Nom : Centrer --
475 -- But : Recentrer le point choisi a l'aide de la souris --
476 -- --
477 -- Parametres ----------------------------------------------------------------------------------
478 -- In out : * La fractal --
479 -- --
480 ------------------------------------------------------------------------------------------------
481 procedure Centrer (Fractal : in out Cara_Fractal) is
482
483
484 Clic_Clavier : Boolean := False; --Savoir si une touche du clavier a ete presse
485 Clic_Souris : Boolean := False; --Savoir si il y a eu un clic de souris
486
487 Touche : Character := Vide; --La touche presse
488
489
490 X, Y , --Coordonnees de la souris (avant le clic)
491 X_Clic, Y_Clic : Natural := 0; --Coordonnees de la souris au moment du clic
492
493 --Sauvegarde des coordonnees de la souris (pour pouvoir effacer la croix)
494 X_Avant, Y_Avant : Natural := 0;
495
496 Pre_Calcul : Long_Float; --Un precalcul
497
498 Centre : T_Centre; --Centre du zoom sans le calcul de l'angle
499
500 begin -- Centrer
501
502 --Boucle s'executant jusqu'a qu'un clic soit fait ou que la touche ESC soit presses
503 while not Clic_Souris and not (Clic_Clavier and Touche = Echape) loop
504
505 Mouse(X, Y); --Lit la position de la souris
506 Dessin_Croix(X, Y); --Dessine une croix a l'emplacement de la souris
507
508 Key_Pressed(Touche, Clic_Clavier); --Lit si une touche est presse
509
510 --Dessine une croix au milieu de l'ecran
511 Dessin_Croix(Largeur_Ecran / 2, Hauteur_Ecran / 2);
512
513 Sleep(10); --Redonne la main au systeme pendant 10ms
514
515 --Si la souris a bougee par rapport a la position precedante alors
516 --efface la croix a la position precedante
517 if X /= X_Avant or Y /= Y_Avant then
518 Efface_Croix(X_Avant, Y_Avant);
519 end if;
520
521 --Sauvegarde la position courante
522 X_Avant := X;
523 Y_Avant := Y;
524
525 --Si un clic est fait => sauvegarde les coordonnees du clic dans X_Clic et Y_Clic
526 --Et Clic_Souris devient vrai (true)
527 Left_Clic(X_Clic, Y_Clic, Clic_Souris);
528
529 end loop;
530
531 --Si la touche ESC du clavier a ete presse alors
532 if Touche = Echape and Clic_Clavier then
533
534 Efface_Croix(X, Y); --Efface la croix sous la souris
535
536 --Efface la croix au milieu de l'ecran
537 Efface_Croix(Largeur_Ecran / 2, Hauteur_Ecran / 2);
538
539 return; --Sort de la procedure
540 end if;
541
542 Pre_Calcul := (2.0 * Long_Float(Largeur_Ecran)) * Fractal.Zoom;
543
544 --Convertie la valeur x du point a l'ecran(pixel) en valeur reel sur la fractal
545 --Voir la doc pour plus d'informations
546 Centre.X := (Long_Float(X_Clic) / Long_Float(Largeur_Ecran) - 0.5)
547 / Fractal.Zoom + Fractal.Centre.X;
548
549 --Convertie la valeur y du point a l'ecran(pixel) en valeur reel sur la fractal
550 --Voir la doc pour plus d'informations
551 Centre.Y := (-2.0 * Long_Float(Y_Clic) + Long_Float(Hauteur_Ecran))
552 / Pre_Calcul + Fractal.Centre.Y;
553
554 --Corrige les valeurs par rapport a l'angle (fractal.angle)
555 Power_Calculator.Change_Angle(Centre.X, Centre.Y, Fractal);
556
557 Fractal.Centre.X := Centre.X;
558 Fractal.Centre.Y := Centre.Y;
559
560 Dessiner_Fractal(Fractal); --Dessine la fractal a l'ecran
561
562 end Centrer;
563
564
565
566 ------------------------------------------------------------------------------------------------
567 -- Nom : Choix_Mosaic --
568 -- But : Choisir a l'aide la souris la fractal courante --
569 -- --
570 -- Parametres ----------------------------------------------------------------------------------
571 -- In : * La liste des farctals a dessiner en vue du chois de l'utilisateur --
572 -- --
573 -- return : * Le numeros de la fractal --
574 -- --
575 ------------------------------------------------------------------------------------------------
576 function Choix_Mosaic (Liste_Fractals : Power_Types.T_Liste_Fractals) return Natural is
577
578 ---------------a enlever apres---------------
579 --Nb_Fractals_Max : Positive := 200;
580 ---------------------------------------------
581 use Power_Types;
582 use Power_List;
583
584 --Pour les fonctions avancees sur le type float
585 package Elementary_Functions_Long_Float
586 is new Ada.Numerics.Generic_Elementary_Functions (Long_Float);
587 use Elementary_Functions_Long_Float;
588 --
589
590 use Spider.User;
591
592 Nb_Fractals : Natural := 0; --Initialise le nombre de farctals dessine a 0
593
594 Nb_Case_X : Positive; --Le nombre de colonne
595 Nb_Case_Y : Positive; --Le nombre de ligne
596
597 Largeur_Case : Long_Float; --La largeur des colonnes
598 Hauteur_Case : Long_Float; --la hauteur des lignes
599
600 X, Y : Long_Float := 0.0; --Pour parcourir toute les cases
601
602 Clic_Souris : Boolean := False; --Savoir si le bouton de la souris a ete presse
603 X_Souris, Y_Souris : Natural; --Les coordonnees de la souris au moment du clic
604 No_Fractal : Positive; --Le numeros de la fractal selectionne lors du clic
605
606 begin --Choix_Mosaic
607
608 --Calcul le nombre de colonne en fonction du nombre de fractals de la liste
609 Nb_Case_X := Integer(Sqrt(Long_Float(Liste_Fractals.Nb_Fractals))) + 1;
610
611 --Calcul le nombre de ligne en fonction du nombre de frctals de la liste
612 Nb_Case_Y := Integer(Long_Float'Truncation(Sqrt(Long_Float(Liste_Fractals.Nb_Fractals))));
613
614 --Calcul la largeur des colonne
615 Largeur_Case := Long_Float(Largeur_Ecran) / Long_Float(Nb_Case_X);
616
617 --calcul la hauteur des lignes
618 Hauteur_Case := Long_Float(Hauteur_Ecran) / Long_Float(Nb_Case_Y);
619
620 --Reinitialise le contenue de la fenetre graphique
621 Spider.Draw.Set_Color_Background(Spider.Draw.Black);
622 Spider.Clear_Window;
623 --
624
625 --Parcour les lignes
626 while Y <= Long_Float(Hauteur_Ecran) - Hauteur_Case / 2.0 loop
627 X:= 0.0;
628
629 --Parcours les colonnes et sort si le nombre de fractal affiche
630 --correspond au nombre de fractal de la liste
631 while X <= Long_Float(Largeur_Ecran) - Largeur_Case / 2.0 and
632 Nb_Fractals /= Liste_Fractals.Nb_Fractals loop
633
634
635 Nb_Fractals := Nb_Fractals + 1; --incremente le nombre de fractal dessine
636 --Dessine la fractal a la bonne place
637 Dessiner_Fractal (Fractal_Num(Liste_Fractals, Nb_Fractals).Fractal ,
638 Integer(X), Integer(Y), Integer(Largeur_Case)-1, Integer(Hauteur_Case)-1);
639
640 --Affiche en haut a gauche de la case son numeros
641 Spider.Draw.Set_Color_Text(Couleur_Numeros);
642 Spider.Move_To(Integer(X), Integer(Y));
643 Spider.Draw.Display_Text(Integer'Image(Nb_Fractals));
644
645
646 X := X + Largeur_Case; --Increment la valeur x
647
648
649 end loop;
650 Y := Y + Hauteur_Case; --Increment la valeur y
651 end loop;
652
653
654 -------------------------------souris clic-----------------------
655 New_Line;
656 Put_Line(" Choose one of them");
657
658 --Boucle qui se repete si l'utilisateur a clique la ou il n'y avait pas de fractal affiche
659 loop
660 --Attends par une boucle le clic de souris
661 loop
662
663
664 Left_Clic(X_Souris, Y_Souris, Clic_Souris); --Si un clic-gauche survient
665 exit when Clic_Souris; --Sort si un clic-gauche est survenu
666
667 --Redonne la main au system pendant 10 ms (il ne faut pas saturer le proc pour rien)
668 Sleep(10);
669 end loop;
670
671 --Calcul la colonne cliquee
672 X_Souris := Integer(Long_Float'Truncation(Long_Float(X_Souris * Nb_Case_X)
673 / Long_Float(Largeur_Ecran))) + 1;
674
675 --Calcul la Ligne cliquee
676 Y_Souris := Integer(Long_Float'Truncation(Long_Float(Y_Souris * Nb_Case_Y)
677 / Long_Float(Hauteur_Ecran))) + 1;
678
679 --Calcul le numeros de la case correspondant a la colonne et a la ligne
680 No_Fractal := X_Souris + (Y_Souris - 1) * Nb_Case_X;
681
682 --Si la case existe alors
683 if No_Fractal <= Liste_Fractals.Nb_Fractals then
684 return No_Fractal;--retourne le numeros de la fractal choisie
685 end if;
686 end loop;
687
688
689 end Choix_Mosaic;
690
691 end Power_Tools;