/*
* 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 { ce, ceIn, cens } from 'src/kernel/dom'
import { getStr } from '../kernel/kernel'
import MacroDlg from './MacroDlg'
import ListeConstFig from './ListeConstFig'
import constantes from '../kernel/constantes'
import ColorButton from '../interface/ColorButton'
import LineStylePanel from '../interface/LineStylePanel'
import $ from 'jquery'
import { getMtgInput } from './dom'
import AvertDlg from '../dialogs/AvertDlg'
import CCbGlob from '../kernel/CCbGlob'
import EditeurConst from '../dialogs/EditeurConst'
import StyleTrait from '../types/StyleTrait'
export default MacConsIterDlg
/**
* Dialogue de création ou modification d'une macro d'implémentation de construction itérative
* @constructor
* @param {MtgApp} app La mtgApp propriétaire
* @param {CMacroConstructionIterative} mac La macro qui doit être modifiée
* @param modification {boolean} : true si le dialogue est ouvert pour modifier une macro déjà existante
* @param callBackOK Fonction de callBack à appeler si on valide par OK
* @param callBackCancel Fonction de callBack à appeler si on referme sans valider
*/
function MacConsIterDlg (app, mac, modification, callBackOK, callBackCancel) {
MacroDlg.call(this, app, mac, modification, callBackOK, callBackCancel)
this.mac = mac
this.modification = modification
let i; let label
const self = this
const tabPrincipal = ce('table', {
cellspacing: 2
})
let tr
let div
this.appendChild(tabPrincipal)
// Ajout de l'éditeur d'intitulé /////////////////////////////////
this.addEditInt(tabPrincipal)
/// ///////////////////////////////////////////////////////////////
// Ajout du pane d'information sur la macro //////////////////////
this.addPaneInfo(tabPrincipal, true) // True pour que le textarea n'ait qu'une ligne
/// //////////////////////////////////////////////////////////////////////////////////////////////
// Un panneau pour le choix de la construction à implémenter
/// //////////////////////////////////////////////////////////////////////////////////////////////
tr = ceIn(tabPrincipal, 'tr')
const tabChoix = ceIn(tr, 'table', {
cellspacing: 2
})
tr = ceIn(tabChoix, 'tr')
let td = ceIn(tr, 'td', {
style: 'vertical-align:middle;'
})
label = ceIn(td, 'label')
$(label).html(getStr('Const') + ' : ')
td = ceIn(tr, 'td', {
style: 'vertical-align:top;width:250px;'
})
this.listeConst = new ListeConstFig(app)
td.appendChild(this.listeConst.select)
this.listeConst.selectElt(modification ? mac.proto : app.doc.tablePrototypes[0])
tr = ceIn(tabPrincipal, 'tr')
const tabInput = ceIn(tr, 'table', { cellspacing: 2 })
tr = ceIn(tabInput, 'tr')
td = ceIn(tr, 'td')
label = ceIn(td, 'label')
$(label).html(getStr('MacItDlg1')) // Nombre d'itération
td = ceIn(tr, 'td')
const input1 = getMtgInput({ id: 'input1', size: 3 })
td.appendChild(input1)
tr = ceIn(tabInput, 'tr')
td = ceIn(tr, 'td')
label = ceIn(td, 'label')
$(label).html(getStr('MacRecDlg5')) // Nombre d'objets sources communs à toutes les itérations
td = ceIn(tr, 'td')
const input2 = getMtgInput({ id: 'input2', size: 3 })
td.appendChild(input2)
// CheckBox pour choisir ou non de donner une couleur spécifique aux objets créés.
tr = ceIn(tabPrincipal, 'tr')
const tabCoul = ceIn(tr, 'table', {
cellspacing: 0
})
tr = ceIn(tabCoul, 'tr')
td = ceIn(tr, 'td')
div = ceIn(td, 'div')
td.appendChild(div)
const cb2 = ceIn(div, 'input', {
id: 'cb2',
type: 'checkbox'
})
cb2.onclick = function () {
$('#tdcoul').css('visibility', $('#cb2').prop('checked') ? 'visible' : 'hidden')
}
label = ceIn(div, 'label', {
for: 'cb2'
})
$(label).html(getStr('MacRecDlg7'))
td = ceIn(tr, 'td', {
id: 'tdcoul'
})
let svg = cens('svg', {
width: Math.floor(constantes.lineStyleWidth),
height: String(constantes.lineStyleWidth / 2)
})
td.appendChild(svg)
this.colorButton = new ColorButton(this, mac.imposerCouleur ? mac.couleurImp : app.getCouleur())
// this.colorButton.container.setAttribute("transform","translate(" + String(constantes.lineStyleWidth + 5) + ",0)");
svg.appendChild(this.colorButton.container)
// Un tableau contenant 3 boutons radio pour choisir si on joint ou non les points fianux
// et si oui si c'est par un polygone ou une ligne brisée
tr = ceIn(tabPrincipal, 'tr')
const tabPtsFinaux = ceIn(tr, 'table', {
cellspacing: 2,
style: 'border:1px solid lightgray'
})
const tdLeft = ceIn(tabPtsFinaux, 'td', {
style: 'vertical-align:top;'
})
const tabPtsFinauxLeft = ceIn(tdLeft, 'table', {
cellspacing: 2
})
const tdRight = ceIn(tabPtsFinaux, 'td', {
id: 'tdright'
}) // Contiendra un éventuel panneau de choix de couleur et de style de trait
tr = ceIn(tabPtsFinauxLeft, 'tr')
div = ceIn(tr, 'div')
const rad1 = ceIn(div, 'input', {
id: 'radlig0',
type: 'radio',
name: 'pts'
})
rad1.onclick = function () {
self.onRadioChange()
}
label = ceIn(div, 'label')
$(label).html(getStr('MacRecDlg9')) // Ne pas joindre
tr = ceIn(tabPtsFinauxLeft, 'tdr')
div = ceIn(tr, 'div')
const rad2 = ceIn(div, 'input', {
id: 'radlig1',
type: 'radio',
name: 'pts'
})
label = ceIn(div, 'label')
$(label).html(getStr('MacRecDlg10')) // Joindre par un polygone
rad2.onclick = function () {
self.onRadioChange()
}
// Si on choisit de remplir par un polygone, on propose une checkbow pour le remplir ou non
tr = ceIn(tabPtsFinauxLeft, 'tr', {
id: 'trpol'
})
div = ceIn(tr, 'div')
ceIn(div, 'input', {
id: 'cb3',
type: 'checkbox',
style: 'margin-left:20px;'
})
label = ceIn(div, 'label', {
for: 'cb3'
})
$(label).html(getStr('MacRecDlg8'))
tr = ceIn(tabPtsFinauxLeft, 'tr')
div = ceIn(tr, 'div')
const rad3 = ceIn(div, 'input', {
id: 'radlig2',
type: 'radio',
name: 'pts'
})
rad3.onclick = function () {
self.onRadioChange()
}
label = ceIn(div, 'label')
$(label).html(getStr('MacRecDlg11')) // Joindre par une ligne brisée
// A droite des trois boutons radio un panneau de choix de couleur et de style si on chosit d'utiliser un
// polygone ou une ligne brisée pour joindre les points finaux
const tabLigne = ceIn(tdRight, 'table', {
cellSpacing: 0,
id: 'tabligne'
})
td = ceIn(tabLigne, 'td')
svg = cens('svg', {
width: Math.floor(2 * constantes.lineStyleWidth + 5),
height: String(6 * constantes.lineStyleButtonHeight)
})
td.appendChild(svg)
const bligne = mac.choixLigne !== 0
this.lineStylePanel = new LineStylePanel(app, bligne ? mac.styleLigne.style : app.getStyleTrait().style)
svg.appendChild(this.lineStylePanel.g)
this.colorLineButton = new ColorButton(this, bligne ? mac.couleurLigne : app.getCouleur())
this.colorLineButton.container.setAttribute('transform', 'translate(' + String(constantes.lineStyleWidth + 5) + ',0)')
svg.appendChild(this.colorLineButton.container)
td = ceIn(tabLigne, 'td', {
style: 'vertical-align:top;'
})
const caption = ceIn(td, 'caption', {
class: 'mtgcaption',
style: 'width:80px;'
})
$(caption).html(getStr('Epaisseur'))
this.select = ceIn(td, 'select', {
size: 4, // Le nombre de lignes visibles par défaut
style: 'width:80px;'
})
for (i = 0; i < 5; i++) {
const option = ceIn(this.select, 'Option', {
class: 'mtgOption'
})
if (i === ((mac.choixLigne === 0) ? 0 : mac.styleLigne.strokeWidth - 1)) option.setAttribute('selected', 'selected')
$(option).html(String(i + 1))
}
if (modification) {
$(input1).val(mac.nbIter)
$(input2).val(mac.nbSourcesPourIter)
// $(input2).attr('disabled', true) // Supprimé version 6.4.2
}
if (mac.imposerCouleur) $(cb2).attr('checked', 'checked')
else $('#tdcoul').css('visibility', 'hidden')
const choixLigne = mac.choixLigne
for (i = 0; i < 3; i++) if (choixLigne === i) $('#radlig' + i).attr('checked', 'checked')
if ((choixLigne === 1) && mac.polygoneRempli) $('#cb3').attr('checked', 'checked')
this.onRadioChange()
this.editeur1 = new EditeurConst(app, input1, 2, 500000, true) // Pour le nombre d'itérations par niveau
this.editeur2 = new EditeurConst(app, input2, 0, 1000, true) // Pour le nombre d'objets communs à toutes les itérations
/// ////////////////////////////////////////////////////////////////////////////////////////////////////
this.addPaneBas(tabPrincipal)
this.create('MacConsItDlg1', 650)
}
MacConsIterDlg.prototype = new MacroDlg()
MacConsIterDlg.prototype.onRadioChange = function () {
$('#tdright').css('display', $('#radlig0').prop('checked') ? 'none' : 'block')
$('#trpol').css('display', $('#radlig1').prop('checked') ? 'block' : 'none')
}
MacConsIterDlg.prototype.OK = function () {
const mac = this.mac
if ($('#inputint').val() !== '') {
if (this.editeur1.validate() && this.editeur2.validate()) {
const nbIter = parseInt($('#input1').val())
const nbSources = parseInt($('#input2').val())
const ch = this.validate(nbSources, nbIter)
if (ch === '') {
mac.nbSourcesPourIter = nbSources
mac.nbIter = nbIter
mac.proto = this.listeConst.getSelectedItem()
mac.imposerCouleur = $('#cb2').prop('checked')
if (mac.imposerCouleur) mac.couleurImp = this.colorButton.color
// On regarde quel est le choix pour les points finaux parmi les 3 rboutons radios proposés
let choix
for (let i = 0; i < 3; i++) {
if ($('#radlig' + i).prop('checked')) {
choix = i
break
}
}
mac.choixLigne = choix
const thickness = this.select.selectedIndex + 1
if (mac.choixLigne !== 0) { // Si on a demandé que les points finaux soient reliés par un polygone ou une ligne brisée
mac.styleLigne = new StyleTrait(this.app.listePr, this.lineStylePanel.style, thickness)
mac.couleurLigne = this.colorLineButton.color
}
if (mac.choixLigne === 1) mac.polygoneRempli = $('#cb3').prop('checked')
this.saveBasic()// Sauvegarde les autres caractéristiques da la macro
this.callBackOK()
if (this.modification) this.app.gestionnaire.enregistreFigureEnCours('ModifObj')
this.destroy()
} else new AvertDlg(this.app, ch, function () { $('#input1').focus() })
}
} else this.avertIncorrect()
}
/**
* Fonction qui analyse si les macros constructions choisies pour chaque niveau d'itération peuvent bien
* être implémentées récursivement avec les choix effectués dans la boîte de dialogue.
* Renvoie "" si tout va bien et sinon une chaîne contenant l'erreur à afficher dans un message d'erreur
*/
/**
* Fonction qui analyse si la macro choisie peut bien être implémentée de façon itérative
* avec les choix effectués dans la boîte de dialogue.
* Renvoie "" si tout va bien et sinon une chaîne contenant l'erreur à afficher dans un message d'erreur
* @param {number} nbSources Le nombre d'objets sources à réutiliser à chaque itération
* @param {number} nbIter Le nombre d'itérations à effectuer
*/
MacConsIterDlg.prototype.validate = function (nbSources, nbIter) {
const
app = this.app
const list = app.listePr
const proto = this.listeConst.getSelectedItem()
const chErr = proto.implementPossible(list)
if (chErr !== '') {
return getStr('ImpImposs') + '\n' + chErr
}
if ((list.pointeurLongueurUnite == null) && proto.utiliseLongueurUnite()) {
// this.listeConst.selectedIndex = i // Supprimé version 6.4.1
return getStr('ErrLong')
}
if (!proto.estIterable(nbSources)) {
// this.listeConst.selectedIndex = i // Supprimé version 6.4.1
return getStr('errIter')
}
// On fait une estimation du nombre d'objets à créer avec le prototype de niveau de récursion 0
const n = (proto.longueur() - proto.nbObjSources - nbSources) * nbIter
if (n > CCbGlob.nombreMaxObj) return getStr('errImpMax')
return ''
}