/*
* MathGraph32 Javascript : Software for animating online dynamic mathematics figures
* https://www.mathgraph32.org/
* @Author Yves Biton (yves.biton@sesamath.net)
* @License: GNU AGPLv3 https://www.gnu.org/licenses/agpl-3.0.html
*/
import NatObj from '../types/NatObj'
import Color from '../types/Color'
import StyleRemplissage from '../types/StyleRemplissage'
import StyleTrait from '../types/StyleTrait'
import CPolygone from './CPolygone'
import CImplementationProto from './CImplementationProto'
import CLigneBrisee from './CLigneBrisee'
import CMacroAvecListe from './CMacroAvecListe'
import CSurfacePolygone from './CSurfacePolygone'
import CNoeudPointeurSurPoint from './CNoeudPointeurSurPoint'
import CSousListeObjets from './CSousListeObjets'
export default CMacroConstructionIterative
/**
* Macro lançant une construction itérative.
* @constructor
* @extends CMacroAvecListe
* @param {CListeObjets} listeProprietaire La liste propriétaire.
* @param {CImplementationProto} impProto null ou la construction propriétaire.
* @param {boolean} estElementFinal true si l'objet est un élément final de construction.
* @param {Color} couleur La couleur d'éciture de l'éditeur (et du cadre éventuel).
* @param {number} xNom L'abscisse d'affichage de la macro
* @param {number} yNom L'ordonnée d'affichage de la macro
* @param {number} decX Décalage horizontal du nom
* @param {number} decY Décalage vertical du nom
* @param {boolean} masque true si l'éditeur est masqué
* @param {CPt} pointLie null ou pointe sur un point auquel l'affichage est lié.
* @param {number} taillePolice Indice de la taiile de police utilisée
* @param {boolean} effacementFond true si on efface le fond de l'en-tête.
* @param {Color} couleurFond La couleur de fond de l'en-tête.
* @param {number} alignementHorizontal 0 pour alignement gauche, 1 pour centre, 2 pour droite.
* @param {number} alignementVertical 0 pour alignement vers le haut, 1 pour centré, 2 pour bas.
* @param {string} intitule Le titre de la macro
* @param {string} commentaireMacro Eventuel commentaire explicatif.
* @param {CListeObjets} listeAssociee liste contenant les éléments à utiliser comme objets sources
* pour la première implémentation de prototype.
* @param {CPrototype} proto La construction à utiliser.
* @param {number} nbIter Le nombre d'iérations souhaité.
* @param {number} nbSourcesPourIter Le nombre d'éléments sources qui sont communs à
* toutes les implémentations.
* @param {boolean} imposerCouleur si true, tous les objets finaux devront prendre la couleur couleurImp.
* @param {Color} couleurImp La couleur des objets finaux si imposerCouleur est true.
* @param {number} choixLigne Si 0, les points finaux ne sont pas reliés, si 1 ils sont reliés
* par un polygone et si 2 reliés par une ligne brisée.
* @param {StyleTrait} styleLigne Le style de trait utilisé si choixLigne n'est pas 0.
* @param {Color} couleurLigne La couleur utilisé pour la ligne si choixLigne n'est pas 0.
* @param {boolean} polygoneRempli true si choixLigne vaut 1 et qu'on souhaite que le polygone soit rempli.
* @param {boolean} fixed true si l'affichage est punaisé et ne peut pas être capturé à la souris
* @returns {CMacroConstructionIterative}
*/
function CMacroConstructionIterative (listeProprietaire, impProto, estElementFinal, couleur,
xNom, yNom, decX, decY, masque, pointLie, taillePolice, effacementFond, couleurFond, alignementHorizontal,
alignementVertical, intitule, commentaireMacro, listeAssociee, proto, nbIter, nbSourcesPourIter,
imposerCouleur, couleurImp, choixLigne, styleLigne, couleurLigne,
polygoneRempli, fixed = false) {
if (arguments.length !== 0) {
if (arguments.length === 1) CMacroAvecListe.call(this, listeProprietaire)
else {
CMacroAvecListe.call(this, listeProprietaire, impProto, estElementFinal, couleur,
xNom, yNom, decX, decY, masque, pointLie, taillePolice, effacementFond, couleurFond,
alignementHorizontal, alignementVertical, intitule, commentaireMacro, listeAssociee, fixed)
this.proto = proto
this.nbIter = nbIter
this.nbSourcesPourIter = nbSourcesPourIter
this.imposerCouleur = imposerCouleur
this.couleurImp = couleurImp
this.choixLigne = choixLigne
this.styleLigne = styleLigne
this.couleurLigne = couleurLigne
this.polygoneRempli = polygoneRempli
}
}
this.dejaExecute = false
}
CMacroConstructionIterative.prototype = new CMacroAvecListe()
CMacroConstructionIterative.prototype.constructor = CMacroConstructionIterative
CMacroConstructionIterative.prototype.superClass = 'CMacroAvecListe'
CMacroConstructionIterative.prototype.className = 'CMacroConstructionIterative'
CMacroConstructionIterative.prototype.getClone = function (listeSource, listeCible) {
const ind1 = listeSource.indexOf(this.pointLie)
const ind2 = listeSource.indexOf(this.impProto)
const listeAssocieeClone = new CSousListeObjets()
listeAssocieeClone.setImage(this.listeAssociee, listeSource, listeCible)
return new CMacroConstructionIterative(listeCible, listeCible.get(ind2, 'CImplementationProto'),
this.estElementFinal, this.couleur, this.xNom, this.yNom, this.decX, this.decY, this.masque,
listeCible.get(ind1, 'CPt'), this.taillePolice,
this.effacementFond, this.couleurFond, this.alignementHorizontal, this.alignementVertical,
this.intitule, this.commentaireMacro, listeAssocieeClone, this.proto, this.nbIter, this.nbSourcesPourIter,
this.imposerCouleur, this.couleurImp, this.choixLigne, this.styleLigne,
this.couleurLigne, this.polygoneRempli, this.fixed)
}
// Version 4.9.7 : On rajoute un paramètre affichage. Les objets ne sont affichés que si le paramètre est présent et true
CMacroConstructionIterative.prototype.execute = function (svg, dimf, couleurFond, affichage) {
let i, gen, impProto, indiceImp, elb, k, poly, ligne
// On implémente la construction de façon itérative
// La liste associée contient les pointeurs sur les objets sources
// On affecte ces éléments aux objets sources du prototype
for (i = 0; i < this.proto.nbObjSources; i++) this.proto.get(i).elementAssocie = this.listeAssociee.get(i)
const liste = this.listeProprietaire
const listePoints = [] // Utilisé si on veut que les points créés soient reliés.
if (this.choixLigne !== 0) {
for (i = 0; i < this.proto.nbObjSources; i++) {
gen = this.proto.get(i)
if (gen.estDeNature(NatObj.NTtPoint)) {
listePoints.push(new CNoeudPointeurSurPoint(liste, gen.elementAssocie))
break
}
}
}
// Version 4.8 : Dans le cas où une (ou plusieurs) implémentation itérative de la construction a déjà été faite, lorsque de nouveaux points nommés
// ou calculs sont créés il faut leur générer un nom. Pour éviter de gros ralentissements lors de l'implémentation, il faut générer ces
// noms avec un suffixe numérique qui commence au nombre d'implémentations plus 1.
impProto = new CImplementationProto(liste, this.proto)
// On implémente la construction une première fois.
indiceImp = liste.longueur()
const indiceImpInitial = indiceImp
impProto.implementePourIter(dimf, liste, this.proto) // Modifié version 4.8
liste.reconstruitChainesCalcul(indiceImpInitial + 1, indiceImpInitial + this.proto.longueur() - this.proto.nbObjSources)
if (this.imposerCouleur) {
for (i = liste.indexOf(impProto) + 1; i < liste.longueur(); i++) {
elb = liste.get(i)
if (elb.estElementFinal && (elb.estDeNature(NatObj.NTtObj))) {
elb.donneCouleur(this.couleurImp)
}
}
}
for (k = 1; k < this.nbIter; k++) {
// On implémente avec les objets finaux sauf ceux qui sont communs aux implémentations
for (i = this.nbSourcesPourIter; i < this.proto.nbObjSources; i++) {
elb = liste.getFinal(indiceImp, i - this.nbSourcesPourIter)
gen = this.proto.get(i)
gen.elementAssocie = elb
}
indiceImp = liste.longueur()
impProto = new CImplementationProto(liste, this.proto)
impProto.implementePourIter(dimf, liste, this.proto) // Modifié version 4.8
if (this.choixLigne !== 0) {
for (i = indiceImp; i < liste.longueur(); i++) {
elb = liste.get(i)
if (elb.estElementFinal && elb.estDeNature(NatObj.NTtPoint)) {
listePoints.push(new CNoeudPointeurSurPoint(liste, elb))
break
}
}
}
if (this.imposerCouleur) {
// On regarde tous les objets finaux et s'ils sont graphiques, on leur donne le style actif
for (i = liste.indexOf(impProto) + 1; i < liste.longueur(); i++) {
elb = liste.get(i)
if (elb.estElementFinal && (elb.estDeNature(NatObj.NTtObj))) {
elb.donneCouleur(this.couleurImp)
}
}
}
}
liste.traiteImplementationsProtoSuccessivesIter(indiceImpInitial, this.proto, this.proto.longueur() - this.proto.nbObjSources)
// Si demandé dans la boîte de dialogue, on relie tous les points créés par un polygone ou une ligne brisée
if (this.choixLigne !== 0) {
if (this.choixLigne === 1) {
listePoints.push(new CNoeudPointeurSurPoint(liste, listePoints[0].pointeurSurPoint))
poly = new CPolygone(liste, null, false, this.couleurLigne, false, this.styleLigne, listePoints)
poly.positionne(false, dimf)
liste.add(poly)
if (this.polygoneRempli) {
const s = new CSurfacePolygone(liste, null, false, this.couleurLigne, false,
StyleRemplissage.transp, poly)
s.positionne(false, dimf)
liste.add(s)
}
} else {
ligne = new CLigneBrisee(liste, null, false, this.couleurLigne, false, this.styleLigne, listePoints)
liste.add(ligne)
ligne.positionne(false, dimf)
}
}
// Correction version 7.3.5 : Le dernier paramètre doit être false pour que l'affichage soit mis sur la pile
// d'appels sinon le setReady4MathJax n'aura pas eu le temps de s'exécuter pour les affchages LaTeX
if ((arguments.length <= 4) || affichage) this.listeProprietaire.afficheTout(indiceImpInitial, svg, true, couleurFond, false) // Pour créer les éléments graphiques
this.termineAction(svg, dimf, couleurFond)
this.dejaExecute = true
// Spécial JavaScript. Dans la version Java c'est fait lors de la sauvegarde de la figure
this.listeProprietaire.etablitListesInternesMacros()
}
CMacroConstructionIterative.prototype.executionPossible = function () {
// Modification version 6.4.9 : On regarde s'il reste encore des implémemations de prototype
// dans la figure. Si la réponse est non c'est que l'utisateur les a toutes détruites et
// on peut alors à nouveau exécuter la macro.
const list = this.listeProprietaire
const nbImpProto = list.nombreImpProto(this.proto.nomProto)
if (nbImpProto === 0) this.dejaExecute = false
return !this.dejaExecute
}
CMacroConstructionIterative.prototype.read = function (inps, list) {
let r, g, b
CMacroAvecListe.prototype.read.call(this, inps, list)
const indProto = inps.readInt()
this.proto = list.documentProprietaire.tablePrototypes[indProto]
this.nbIter = inps.readInt()
this.nbSourcesPourIter = inps.readInt()
this.imposerCouleur = inps.readBoolean()
if (this.imposerCouleur) {
r = inps.readByte()
g = inps.readByte()
b = inps.readByte()
this.couleurImp = new Color(r, g, b)
}
this.choixLigne = inps.readInt()
if (this.choixLigne !== 0) {
r = inps.readByte()
g = inps.readByte()
b = inps.readByte()
this.couleurLigne = new Color(r, g, b)
this.styleLigne = new StyleTrait(list)
if (list.numeroVersion < 15) this.styleLigne.readOld(inps, list, false)
else this.styleLigne.read(inps, list)
if (this.choixLigne === 1) {
// Polygone
this.polygoneRempli = inps.readBoolean()
}
}
}
CMacroConstructionIterative.prototype.write = function (oups, list) {
CMacroAvecListe.prototype.write.call(this, oups, list)
// On enregistre l'indice du prototype utilisé dans la table des prototype du document
oups.writeInt(list.documentProprietaire.tablePrototypes.indexOf(this.proto))
oups.writeInt(this.nbIter)
oups.writeInt(this.nbSourcesPourIter)
oups.writeBoolean(this.imposerCouleur)
if (this.imposerCouleur) {
oups.writeByte(this.couleurImp.getRed())
oups.writeByte(this.couleurImp.getGreen())
oups.writeByte(this.couleurImp.getBlue())
}
oups.writeInt(this.choixLigne)
if (this.choixLigne !== 0) {
oups.writeByte(this.couleurLigne.getRed())
oups.writeByte(this.couleurLigne.getGreen())
oups.writeByte(this.couleurLigne.getBlue())
// oups.writeInt(this.styleLigne) // Correction version 6.4.1
this.styleLigne.write(oups)
if (this.choixLigne === 1) oups.writeBoolean(this.polygoneRempli)
}
}