/*
* 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 Nat from '../types/Nat'
import Pointeur from '../types/Pointeur'
import { distancePointPoint, distMinForMouse, distMinForTouch, preventDefault } from '../kernel/kernel'
import { mousePosition, touchPosition } from '../kernel/kernelAdd'
import OutilPointage from './OutilPointage'
import ChoixTypeDlg from '../dialogs/ChoixTypeDlg'
import ChoixObjProchesDlg from 'src/dialogs/ChoixObjProchesDlg'
export default OutilPointageCapture
/**
* Outil de pountage utilisé par l'outil de capture d'objet mobile
* Hérite de OutilPointage
* @param {MtgApp} app L'application propriétaire
* @constructor
*/
function OutilPointageCapture (app) {
OutilPointage.call(this, app)
}
OutilPointageCapture.prototype = new OutilPointage()
OutilPointageCapture.prototype.reset = function () {
OutilPointage.prototype.reset.call(this)
this.objetPredesigne = null
this.cadre_Ver_Proche = false // Indique si on est en train de capturer la partie verticale du cadre d'affichage
this.cadre_Hor_Proche = false // Indique si on est en train de capturer la partie horizontale du cadre d'affichage
this.cadre_Ver_Capt = false // Indique si on est en train de capturer la partie verticale du cadre d'affichage
this.cadre_Hor_Capt = false // Indique si on est en train de capturer la partie horizontale du cadre d'affichage
}
OutilPointageCapture.prototype.mousemove = function (evt) {
this.devicemove(evt, 'mouse', mousePosition)
}
OutilPointageCapture.prototype.touchmove = function (evt) {
this.devicemove(evt, 'touch', touchPosition)
}
OutilPointageCapture.prototype.devicemove = function (evt, type, fonc) {
let point
const app = this.app
const svg = app.svgFigure
const doc = app.doc
const list = doc.listePr
// Sur les périphériques mobiles il peut y avoir deux événements générés quand on touche l'écran : onmousedown et ontouchstart
// if (doc.type && (doc.type != type)) return;
if ((type === 'mouse') && (doc.type === 'touch')) return
doc.type = type
const elc = app.elementCapture
const tab = fonc(svg, evt, app.zoomFactor)
const x = tab.x
const y = tab.y
// if (x<0 || x>app.dimf.x || y<0 || y>app.dimf.y) return; // Devenu inutile depuis que les événements sont interceptés par un rectangle
if (this.cadre_Ver_Capt || this.cadre_Hor_Capt) {
let w = app.widthCadre; let h = app.heightCadre
app.deleteCadre()
if ((this.cadre_Ver_Capt) && (x > 20)) w = Math.round(x)
if ((this.cadre_Hor_Capt) && (y > 20)) h = Math.round(y)
app.createCadre(w, h)
} else {
if (elc === null) {
if (app.translatable && app.isTranslating) {
app.outilCapt.cursor = 'move'
const point = fonc(svg, evt, app.zoomFactor)
const x = point.x
const y = point.y
const decx = x - this.xInitSouris
const decy = y - this.yInitSouris
if ((decx !== 0) || (decy !== 0)) {
const modif = list.translateDe(decx, decy)
if (modif) {
this.xInitSouris = x
this.yInitSouris = y
list.positionne(false, app.dimf)
list.update(svg, app.doc.couleurFond, true, true) // Modifié version 6.4.8
}
}
} else {
const info = this.app.infoProx
const nbObjetsProches = doc.listePr.procheDePourCapture(this.aDesigner,
tab, info, app.listeExclusion, true, type)
if ((nbObjetsProches === 0) && app.cadre) {
const distmin = type === 'touch' ? distMinForTouch : distMinForMouse
this.cadre_Ver_Proche = Math.abs(x - app.widthCadre) <= distmin
this.cadre_Hor_Proche = Math.abs(y - app.heightCadre) <= distmin
app.outilActif.cursor = (this.cadre_Hor_Proche || this.cadre_Ver_Proche) ? 'pointer' : 'default'
} else app.outilActif.cursor = (nbObjetsProches > 0) ? 'pointer' : 'default'
}
} else {
const dimf = doc.dimf
const couleurFond = doc.couleurFond
if (elc.estDeNature(NatObj.NPointMobile)) {
if ((Math.abs(x - elc.x) >= 1) || (Math.abs(y - elc.y) >= 1)) {
point = { x: 0, y: 0 }
const abs = new Pointeur()
const b = elc.testDeplacement(dimf, x, y, point, abs)
if (b) {
if (elc.estDeNature(NatObj.NPointCapturableNonLie)) {
elc.placeEn(point.x, point.y)
} else if (elc.estDeNature(NatObj.NPointLie)) {
elc.donneAbscisse(abs.getValue())
}
}
}
} else {
if (elc.estDeNature(NatObj.NMarqueAngle)) {
const ray = distancePointPoint(x, y, elc.centreX, elc.centreY)
if (ray > 3) elc.setRayon(ray)
} else {
if (elc.estDeNature(NatObj.NAffLieAPoint)) {
const pt = elc.pointLie
if (pt === null) {
const dx = x - this.xInitSouris
const dy = y - this.yInitSouris
if ((dx !== 0) || (dy !== 0)) {
elc.placeNom(this.xAffInitial + dx, this.yAffInitial + dy)
}
} else {
elc.decaleNom(this.xdecalageInitialRelatifAffichage + x - this.xInitSouris,
this.ydecalageInitialRelatifAffichage + y - this.yInitSouris)
}
} else {
if (elc.estDeNature(NatObj.NLieuObjet)) {
// Si ce lieu d'objet est capturable c'est qu'il est généré par un CCommentaire ou un CLatex
// CLieuObjetAncetre lieu = (CLieuObjetAncetre) elementCapture;
// Si l'affichage générant le lieu d'objet n'a pas été punaisé on déplace l'affichage
// qui a généré le lieu d'objets ce qui dépalce le lieu d'objets lui-même.
// c'est le cas par exemple pour les graduations d'un repère
const aff = elc.elementAssocie
if (!aff.fixed) {
aff.decaleNom(this.xdecalageInitialRelatifAffichage + x - this.xInitSouris,
this.ydecalageInitialRelatifAffichage + y - this.yInitSouris)
}
} else {
elc.decaleNom(this.xdecalageInitialRelatifAffichage + x - this.xInitSouris,
this.ydecalageInitialRelatifAffichage + y - this.yInitSouris)
}
}
}
}
app.listeARecalculer.positionne(false, dimf)
// Ligne suivante modifié version 6.4.8 (ajout du dernier paramètre)
app.listeARecalculer.update(svg, couleurFond, true, true)
}
}
}
OutilPointageCapture.prototype.mousedown = function (evt) {
this.devicedown(evt, 'mouse', mousePosition)
}
OutilPointageCapture.prototype.touchstart = function (evt) {
this.devicedown(evt, 'touch', touchPosition)
}
OutilPointageCapture.prototype.devicedown = function (evt, type, fonc) {
const app = this.app
let mac
const svg = app.svgFigure
const doc = app.doc
if (!doc.isActive) return
const liste = doc.listePr
const dimf = doc.dimf
const couleurFond = doc.couleurFond
// Sur les périphériques mobiles il peut y avoir deux événements générés quand on touche l'écran : onmousedown et ontouchstart
// if (doc.type && (doc.type != type)) return;
if ((type === 'mouse') && (doc.type === 'touch')) return
doc.type = type
if (app.elementCapture !== null) {
app.elementCapture = null
app.listeARecalculer.retireTout()
return
}
if (liste.macroEnCours !== null) {
mac = liste.macroEnCours.macroEnCours()
if ((mac.className === 'CMacroPause') && (mac.dureePause === 0)) {
mac.passageMacroSuiv(svg, dimf, couleurFond)
return
}
if ((mac !== null) && (mac.className === 'CMacroApparition') && mac.executionPossible()) {
mac.execute(svg, dimf, couleurFond, true)
// Attention mac ne pointe plus forcément sur la macro en cours
if (!liste.macroEnCours.macroEnCours().executionEnCours) liste.macroEnCours.passageMacroSuiv(svg, dimf, couleurFond)
return
}
}
const info = this.app.infoProx
const point = fonc(svg, evt, app.zoomFactor)
// if (point.x<0 || point.x>app.dimf.x || point.y<0 || point.y>app.dimf.y) return;
this.xInitSouris = point.x
this.yInitSouris = point.y
const nbObjetsProches = liste.procheDePourCapture(this.aDesigner,
point, info, app.listeExclusion, true, type)
if (nbObjetsProches > 0) {
if ((mac = info.infoParType[NatObj.indiceMacro].premierVoisin) !== null) {
if (mac.executionEnCours) {
mac.macroEnCours().termineAction(svg, dimf, couleurFond)
}
}
if (!liste.documentProprietaire.modeTraceActive) liste.deleteTraces()
if (this.objetPredesigne !== null) {
const dist = type === 'touch' ? distMinForTouch : distMinForMouse
if (this.objetPredesigne.distancePoint(point.x, point.y, true, dist) < dist) {
app.elementCapture = this.objetPredesigne
this.objetPredesigne = null
this.callBackAfterChoice()
}
} else {
if (app.elementCapture === null) {
const self = this
if (info.premierPointVoisin !== null) { // Priorité aux points
if (info.nombrePointsVoisins === 1) {
app.elementCapture = info.premierPointVoisin
this.callBackAfterChoice()
} else {
preventDefault(evt)
evt.stopPropagation()
if (info.nombreTypesProches > 1) {
new ChoixTypeDlg(app, info, Nat.and(info.typesProches, NatObj.NPointMobile), this,
'objetPredesigne', point, type, function () {
self.callBackAfterChoice()
})
} else {
// Si plusieurs objets du type choisi on lance une boîte de dialogue de choix de l'objet de ce type
/*
new PremierDernierDlg(app, this, 'objetPredesigne', info.premierPointVoisin,
info.dernierPointVoisin, function () {
self.callBackAfterChoice()
})
*/
new ChoixObjProchesDlg(app, this, 'objetPredesigne', info.typesProches, point,
app.listeExclusion, type, false, false, self.callBackAfterChoice)
}
}
} else {
if (info.nombreTypesProches > 1) {
new ChoixTypeDlg(app, info, info.typesProches, this,
'objetPredesigne', point, type, function () {
self.callBackAfterChoice()
})
} else {
if (nbObjetsProches === 1) {
app.elementCapture = info.premierVoisin()
this.callBackAfterChoice()
} else {
// Si plusieurs objets du type choisi on lance une boîte de dialogue de choix de l'objet de ce type
/*
new PremierDernierDlg(app, this, 'objetPredesigne', info.premierVoisin(),
info.dernierVoisin(), function () {
self.callBackAfterChoice()
})
*/
new ChoixObjProchesDlg(app, this, 'objetPredesigne', info.typesProches, point,
app.listeExclusion, type, false, false, self.callBackAfterChoice)
}
}
}
}
}
} else {
if (liste.macroEnCours !== null) {
if (liste.macroEnCours.className === 'CMacroSuiteMacros') {
mac = liste.macroEnCours.macroEnCours()
if (mac.arretParClic()) {
mac.termineAction(svg, dimf, couleurFond)
liste.macroEnCours.passageMacroSuiv(svg, dimf, couleurFond)
}
} else {
// Si la macro en cours est une macro d'apparition avec clic pour objet suivant
// on ne la désactive que si on est au dernier objet
mac = liste.macroEnCours.macroEnCours()
if ((mac.className === 'CMacroApparition') && mac.executionEnCours) {
this.liste.update(svg, couleurFond)
} else {
if (mac.arretParClic()) mac.termineAction(svg, dimf, couleurFond)
}
}
} else {
if (this.cadre_Ver_Proche) this.cadre_Ver_Capt = true
if (this.cadre_Hor_Proche) this.cadre_Hor_Capt = true
// Version 8.0. On donne la possibilité de translater la figure si aucun objet capturable
// n'est proche et si le cadre de sélection n'est pas proche non plus.
if (!this.cadre_Ver_Proche && !this.cadre_Hor_Proche && app.translatable) app.isTranslating = true
}
}
}
// Fonction appelée après un clic de souris lorsqu'un dialogue de choix est apparu
// ou lorsqu'un seul objet était proche de la souris
OutilPointageCapture.prototype.callBackAfterChoice = function () {
const app = this.app
const doc = app.doc
const elc = app.elementCapture
let affEffectif
if (elc !== null) {
if (elc.estDeNature(Nat.or(NatObj.NAffLieAPoint, NatObj.NLieuObjet))) {
if (elc.estDeNature(NatObj.NLieuObjet)) {
// l'affichage générant le lieu d'objets étant souvent caché, son rectAff.x
// et son rectAff.y peuvent être nuls.
affEffectif = elc.elementAssocie
} else {
affEffectif = elc
}
this.xdecalageInitialRelatifAffichage = affEffectif.decX
this.ydecalageInitialRelatifAffichage = affEffectif.decY
this.xAffInitial = affEffectif.xNom
this.yAffInitial = affEffectif.yNom
/// ////////////////////////////////////
// Supprimé version 6.0. Inutile
// this.rectAffxInitial = aff.rectAff.x;
// this.rectAffyInitial = aff.rectAff.y;
/// /////////////////////////////////////
}
app.listeARecalculer.retireTout()
app.listeARecalculer.ajouteObjetsDependantsSauf(app.elementCapture, doc.listePr, null)
}
}
OutilPointageCapture.prototype.deviceup = function () {
this.app.doc.type = '' // Pour autoriser à nouveau tous les événements souris ou touch
const app = this.app
const svg = this.app.svgFigure
const doc = this.app.doc
this.cadre_Ver_Capt = false
this.cadre_Hor_Capt = false
document.body.style.cursor = 'default'
if (app.elementCapture !== null) {
app.elementCapture = null
// Ligne suivante modifié version 6.4.8 (ajout du dernier paramètre)
app.listeARecalculer.update(svg, doc.couleurFond, true, true)
app.listeARecalculer.retireTout()
app.outilCapt.saveFig()
} else {
if (app.translatable && app.isTranslating) {
app.outilCapt.saveFig()
app.isTranslating = false
}
}
}
OutilPointageCapture.prototype.touchend = function () {
this.deviceup()
}
OutilPointageCapture.prototype.touchcancel = function () {
this.deviceup()
}
OutilPointageCapture.prototype.mouseup = function () {
this.deviceup()
}