Index: gc_lang/fr/tb/content/lex_editor.css ================================================================== --- gc_lang/fr/tb/content/lex_editor.css +++ gc_lang/fr/tb/content/lex_editor.css @@ -69,21 +69,21 @@ } .other_textbox { width: 250px; } -#generated_words { +#generated_words_table { width: 400px; - height: 620px; + height: 600px; } /* Lexicon tab */ -#lexicon { +#lexicon_table { width: 600px; height: 650px; } .info_label { Index: gc_lang/fr/tb/content/lex_editor.js ================================================================== --- gc_lang/fr/tb/content/lex_editor.js +++ gc_lang/fr/tb/content/lex_editor.js @@ -1,4 +1,498 @@ // JavaScript "use strict"; +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; +const prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService).getBranch("extensions.grammarchecker."); + + +/* + Common functions +*/ + +function showError (e) { + Cu.reportError(e); + console.error(e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message); +} + +function createNode (sType, oAttr) { + try { + let xNode = document.createElement(sType); + Object.assign(xNode, oAttr); + return xNode; + } + catch (e) { + showError(e); + } +} + +function enableElement (sElemId) { + if (document.getElementById(sElemId)) { + document.getElementById(sElemId).disabled = false; + } else { + console.log("HTML node named <" + sElemId + "> not found.") + } +} + +function disableElement (sElemId) { + if (document.getElementById(sElemId)) { + document.getElementById(sElemId).disabled = true; + } else { + console.log("HTML node named <" + sElemId + "> not found.") + } +} + + + +document.getElementById("save_button").addEventListener("click", () => { oBinaryDict.build(); }, false); + + + +class Table { + + constructor (sNodeId, lColumn, lColumnWidth, sProgressBarId, sResultId="") { + this.sNodeId = sNodeId; + this.xTable = document.getElementById(sNodeId); + this.nColumn = lColumn.length; + this.lColumn = lColumn; + this.lColumnWidth = lColumnWidth; + this.xProgressBar = document.getElementById(sProgressBarId); + this.xNumEntry = document.getElementById(sResultId); + this.iEntryIndex = 0; + this.lEntry = []; + this.nEntry = 0 + this._createHeader(); + this.listen(); + } + + _createHeader () { + let xListheadNode = createNode("listhead"); + xListheadNode.appendChild(createNode("listheader", { label: "·", width: "12px" })); + //xListheadNode.appendChild(createNode("listheader", { label: "#" })); + for (let sColumn of this.lColumn) { + xListheadNode.appendChild(createNode("listheader", { label: sColumn })); + } + this.xTable.appendChild(xListheadNode); + let xListcolsNode = createNode("listcols"); + for (let cColumn of this.lColumnWidth) { + xListcolsNode.appendChild(createNode("listcol", { flex: cColumn })); + } + this.xTable.appendChild(xListcolsNode); + } + + clear () { + while (this.xTable.firstChild) { + this.xTable.removeChild(this.xTable.firstChild); + } + this.iEntryIndex = 0; + this._createHeader(); + } + + fill (lFlex) { + this.clear(); + if (lFlex.length > 0) { + this.xProgressBar.max = lFlex.length; + this.xProgressBar.value = 1; + for (let lData of lFlex) { + this._addRow(lData); + this.xProgressBar.value += 1; + } + this.xProgressBar.value = this.xProgressBar.max; + } + this.lEntry = lFlex; + this.nEntry = lFlex.length; + this.showEntryNumber(); + } + + addEntries (lFlex) { + this.lEntry.push(...lFlex); + for (let lData of lFlex) { + this._addRow(lData); + } + this.nEntry += lFlex.length; + this.showEntryNumber(); + } + + showEntryNumber () { + if (this.xNumEntry) { + this.xNumEntry.textContent = this.nEntry; + } + } + + _addRow (lData) { + let xRowNode = createNode("listitem", { id: this.sNodeId + "_row_" + this.iEntryIndex }); + xRowNode.appendChild(createNode("listcell", { label: "×", className: "delete_entry", title: "Effacer cette entrée", value: this.iEntryIndex })); + //xRowNode.appendChild(createNode("listcell", { label: this.iEntryIndex })); + for (let data of lData) { + xRowNode.appendChild(createNode("listcell", { label: data })); + } + this.xTable.appendChild(xRowNode); + this.iEntryIndex += 1; + } + + listen () { + this.xTable.addEventListener("click", (xEvent) => { this.onTableClick(xEvent); }, false); + } + + onTableClick (xEvent) { + try { + let xElem = xEvent.target; + if (xElem.className) { + if (xElem.className == "delete_entry") { + this.deleteRow(xElem.value); + } + } + } + catch (e) { + showError(e); + } + } + + deleteRow (iEntry) { + this.lEntry[parseInt(iEntry)] = null; + if (document.getElementById(this.sNodeId + "_row_" + iEntry)) { + document.getElementById(this.sNodeId + "_row_" + iEntry).style.display = "none"; + } + this.nEntry -= 1; + this.showEntryNumber(); + } + + getEntries () { + return this.lEntry.filter((e) => e !== null); + } +} + + +const oGenerator = { + + sLemma: "", + + cMainTag: "", + + lFlexion: [], + + listen: function () { + document.getElementById("lemma").addEventListener("keyup", () => { this.update(); }, false); + // nom commun + document.getElementById("tag_N").addEventListener("click", () => { this.update("N"); }, false); + document.getElementById("nom_adj").addEventListener("click", () => { this.update(); }, false); + document.getElementById("nom").addEventListener("click", () => { this.update(); }, false); + document.getElementById("adj").addEventListener("click", () => { this.update(); }, false); + document.getElementById("N_epi").addEventListener("click", () => { this.update(); }, false); + document.getElementById("N_mas").addEventListener("click", () => { this.update(); }, false); + document.getElementById("N_fem").addEventListener("click", () => { this.update(); }, false); + document.getElementById("N_s").addEventListener("click", () => { this.update(); }, false); + document.getElementById("N_x").addEventListener("click", () => { this.update(); }, false); + document.getElementById("N_inv").addEventListener("click", () => { this.update(); }, false); + document.getElementById("lemma2").addEventListener("keyup", () => { this.update(); }, false); + // nom propre + document.getElementById("tag_M").addEventListener("click", () => { this.update("M"); }, false); + document.getElementById("M1").addEventListener("click", () => { this.update(); }, false); + document.getElementById("M2").addEventListener("click", () => { this.update(); }, false); + document.getElementById("MP").addEventListener("click", () => { this.update(); }, false); + document.getElementById("M_epi").addEventListener("click", () => { this.update(); }, false); + document.getElementById("M_mas").addEventListener("click", () => { this.update(); }, false); + document.getElementById("M_fem").addEventListener("click", () => { this.update(); }, false); + // verbe + document.getElementById("tag_V").addEventListener("click", () => { this.update("V"); }, false); + document.getElementById("v_i").addEventListener("click", () => { this.update(); }, false); + document.getElementById("v_t").addEventListener("click", () => { this.update(); }, false); + document.getElementById("v_n").addEventListener("click", () => { this.update(); }, false); + document.getElementById("v_p").addEventListener("click", () => { this.update(); }, false); + document.getElementById("v_m").addEventListener("click", () => { this.update(); }, false); + document.getElementById("v_ae").addEventListener("click", () => { this.update(); }, false); + document.getElementById("v_aa").addEventListener("click", () => { this.update(); }, false); + document.getElementById("v_ppas").addEventListener("click", () => { this.update(); }, false); + document.getElementById("verbe_modele").addEventListener("keyup", () => { this.update(); }, false); + // adverbe + document.getElementById("tag_W").addEventListener("click", () => { this.update("W"); }, false); + // autre + document.getElementById("tag_X").addEventListener("click", () => { this.update("X"); }, false); + document.getElementById("flexion").addEventListener("keyup", () => { this.update(); }, false); + document.getElementById("tags").addEventListener("keyup", () => { this.update(); }, false); + // ajout + document.getElementById("add_to_lexicon").addEventListener("click", () => { this.addToLexicon(); }, false); + }, + + clear: function () { + try { + // nom commun + document.getElementById("tag_N").checked = false; + document.getElementById("nom_adj").checked = false; + document.getElementById("nom").checked = false; + document.getElementById("adj").checked = false; + document.getElementById("N_epi").checked = false; + document.getElementById("N_mas").checked = false; + document.getElementById("N_fem").checked = false; + document.getElementById("N_s").checked = false; + document.getElementById("N_x").checked = false; + document.getElementById("N_inv").checked = false; + document.getElementById("lemma2").value = ""; + // nom propre + document.getElementById("tag_M").checked = false; + document.getElementById("M1").checked = false; + document.getElementById("M2").checked = false; + document.getElementById("MP").checked = false; + document.getElementById("M_epi").checked = false; + document.getElementById("M_mas").checked = false; + document.getElementById("M_fem").checked = false; + // verbe + document.getElementById("tag_V").checked = false; + document.getElementById("v_i").checked = false; + document.getElementById("v_t").checked = false; + document.getElementById("v_n").checked = false; + document.getElementById("v_p").checked = false; + document.getElementById("v_m").checked = false; + document.getElementById("v_ae").checked = false; + document.getElementById("v_aa").checked = false; + document.getElementById("v_ppas").checked = true; + document.getElementById("verbe_modele").value = ""; + // adverbe + document.getElementById("tag_W").checked = false; + // autre + document.getElementById("tag_X").checked = false; + document.getElementById("flexion").value = ""; + document.getElementById("tags").value = ""; + } + catch (e) { + showError(e); + } + }, + + lTag: ["N", "M", "V", "W", "X"], + + setMainTag: function (cTag) { + this.cMainTag = cTag; + for (let c of this.lTag) { + if (c !== cTag) { + document.getElementById("tag_"+cTag).checked = false; + } + } + }, + + update: function (cTag=null) { + if (cTag !== null) { + this.setMainTag(cTag); + } + try { + this.lFlexion = []; + this.sLemma = document.getElementById("lemma").value.trim(); + if (this.sLemma.length > 0) { + switch (this.cMainTag) { + case "N": + if (!this.getRadioValue("pos_nom_commun") || !this.getRadioValue("genre_nom_commun")) { + break; + } + let sTag = this.getRadioValue("pos_nom_commun") + this.getRadioValue("genre_nom_commun"); + switch (this.getRadioValue("pluriel_nom_commun")) { + case "s": + this.lFlexion.push([this.sLemma, sTag+":s/*"]); + this.lFlexion.push([this.sLemma+"s", sTag+":p/*"]); + break; + case "x": + this.lFlexion.push([this.sLemma, sTag+":s/*"]); + this.lFlexion.push([this.sLemma+"x", sTag+":p/*"]); + break; + case "i": + this.lFlexion.push([this.sLemma, sTag+":i/*"]); + break; + } + let sLemma2 = document.getElementById("lemma2").value.trim(); + if (sLemma2.length > 0 && this.getRadioValue("pos_nom_commun2") && this.getRadioValue("genre_nom_commun2")) { + let sTag2 = this.getRadioValue("pos_nom_commun2") + this.getRadioValue("genre_nom_commun2"); + switch (this.getRadioValue("pluriel_nom_commun2")) { + case "s": + this.lFlexion.push([sLemma2, sTag2+":s/*"]); + this.lFlexion.push([sLemma2+"s", sTag2+":p/*"]); + break; + case "x": + this.lFlexion.push([sLemma2, sTag2+":s/*"]); + this.lFlexion.push([sLemma2+"x", sTag2+":p/*"]); + break; + case "i": + this.lFlexion.push([sLemma2, sTag2+":i/*"]); + break; + } + } + break; + case "V": { + if (!this.sLemma.endsWith("er") && !this.sLemma.endsWith("ir") && !this.sLemma.endsWith("re")) { + break; + } + this.sLemma = this.sLemma.toLowerCase(); + let cGroup = ""; + let c_i = (document.getElementById("up_v_i").checked) ? "i" : "_"; + let c_t = (document.getElementById("up_v_t").checked) ? "t" : "_"; + let c_n = (document.getElementById("up_v_n").checked) ? "n" : "_"; + let c_p = (document.getElementById("up_v_p").checked) ? "p" : "_"; + let c_m = (document.getElementById("up_v_m").checked) ? "m" : "_"; + let c_ae = (document.getElementById("up_v_ae").checked) ? "e" : "_"; + let c_aa = (document.getElementById("up_v_aa").checked) ? "a" : "_"; + let sVerbTag = c_i + c_t + c_n + c_p + c_m + c_ae + c_aa; + if (!sVerbTag.endsWith("__") && !sVerbTag.startsWith("____")) { + let sVerbPattern = document.getElementById("verb_pattern").value.trim(); + if (sVerbPattern.length == 0) { + // utilisation du générateur de conjugaison + let bVarPpas = document.getElementById("up_partpas").checked; + for (let [sFlexion, sFlexTags] of conj_generator.conjugate(this.sLemma, sVerbTag, bVarPpas)) { + this.lFlexion.push([sFlexion, sFlexTags]); + } + } else { + // copie du motif d’un autre verbe : utilisation du conjugueur + if (conj.isVerb(sVerbPattern)) { + let oVerb = new Verb(this.sLemma, sVerbPattern); + for (let [sTag1, dFlex] of oVerb.dConj.entries()) { + if (sTag1 !== ":Q") { + for (let [sTag2, sConj] of dFlex.entries()) { + if (sTag2.startsWith(":") && sConj !== "") { + this.lFlexion.push([sConj, ":V" + oVerb.cGroup + "_" + sVerbTag + sTag1 + sTag2]); + } + } + } else { + // participes passés + if (dFlex.get(":Q3") !== "") { + if (dFlex.get(":Q2") !== "") { + this.lFlexion.push([dFlex.get(":Q1"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:m:s/*"]); + this.lFlexion.push([dFlex.get(":Q2"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:m:p/*"]); + } else { + this.lFlexion.push([dFlex.get(":Q1"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:m:i/*"]); + } + this.lFlexion.push([dFlex.get(":Q3"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:f:s/*"]); + this.lFlexion.push([dFlex.get(":Q4"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:f:p/*"]); + } else { + this.lFlexion.push([dFlex.get(":Q1"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:e:i/*"]); + } + } + } + } + } + } + break; + } + case "W": + this.sLemma = this.sLemma.toLowerCase(); + this.lFlexion.push([this.sLemma, ":W/*"]); + break; + case "M": + this.sLemma = this.sLemma.slice(0,1).toUpperCase() + this.sLemma.slice(1); + let sPOSTag = this.getRadioValue("pos_nom_propre") + let sGenderTag = this.getRadioValue("genre_nom_propre"); + if (sGenderTag) { + this.lFlexion.push([this.sLemma, sPOSTag+sGenderTag+":i/*"]); + } + break; + case "X": + let sFlexion = document.getElementById("flexion").value.trim(); + let sTags = document.getElementById("tags").value.trim(); + if (sFlexion.length > 0 && sTags.startsWith(":")) { + this.lFlexion.push([sFlexion, sTags]); + } + break; + } + } + oGenWordsTable.fill(this.lFlexion); + } + catch (e) { + showError(e); + } + }, + + getRadioValue: function (sName) { + if (document.getElementById(sName)) { + for (let xNode of document.getElementById(sName).children) { + if (xNode.selected) { + return xNode.value; + } + } + } + return null; + }, + + createFlexLemmaTagArray: function () { + let lEntry = []; + for (let [sFlex, sTags] of oGenWordsTable.getEntries()) { + lEntry.push([sFlex, this.sLemma, sTags]); + } + return lEntry; + }, + + addToLexicon: function () { + try { + oLexiconTable.addEntries(this.createFlexLemmaTagArray()); + oGenWordsTable.clear(); + document.getElementById("lemma").value = ""; + document.getElementById("lemma").focus(); + enableElement("save_button"); + this.clear(); + this.cMainTag = ""; + } + catch (e) { + showError(e); + } + } +} + + +const oBinaryDict = { + + oIBDAWG: null, + + load: function () { + let sJSON = prefs.getCharPref("oPersonalDictionary"); + if (sJSON != "") { + let oJSON = JSON.parse(sJSON); + this.oIBDAWG = new IBDAWG(oJSON); + let lEntry = []; + for (let s of this.oIBDAWG.select()) { + lEntry.push(s.split("\t")); + } + oLexiconTable.fill(lEntry); + this.setDictData(this.oIBDAWG.nEntry, this.oIBDAWG.sDate); + enableElement("export_button"); + } + }, + + setDictData: function (nEntries, sDate) { + document.getElementById("dic_num_entries").textContent = nEntries; + document.getElementById("dic_save_date").textContent = sDate; + }, + + listen: function () { + document.getElementById("export_button").addEventListener("click", () => { this.export(); }, false); + //document.getElementById("import_button").addEventListener("click", () => { this.import(); }, false); + }, + + build: function () { + let xProgressNode = document.getElementById("wait_progress"); + let lEntry = oLexiconTable.getEntries(); + if (lEntry.length > 0) { + let oDAWG = new DAWG(lEntry, "S", "fr", "Français", "Dictionnaire personnel", xProgressNode); + let oJSON = oDAWG.createBinaryJSON(1); + prefs.setCharPref("oPersonalDictionary", JSON.stringify(oJSON)); + this.oIBDAWG = new IBDAWG(oJSON); + this.setDictData(this.oIBDAWG.nEntry, this.oIBDAWG.sDate); + browser.runtime.sendMessage({ sCommand: "setDictionary", dParam: {sType: "personal", oDict: oJSON}, dInfo: {} }); + } + enableElement("export_button"); + }, + + import: function () { + console.log("import"); + }, + + export: function () { + let xBlob = new Blob([ JSON.stringify(this.oIBDAWG.getJSON()) ], {type: 'application/json'}); + let sURL = URL.createObjectURL(xBlob); + browser.downloads.download({ filename: "fr.personal.json", url: sURL, saveAs: true }); + } +} + + +const oLexiconTable = new Table("lexicon_table", ["Flexions", "Lemmes", "Étiquettes"], [4, 3, 4],"progress_lexicon", "num_entries"); +const oGenWordsTable = new Table("generated_words_table", ["Flexions", "Étiquettes"], [1, 1], "progress_new_words"); + +oBinaryDict.load(); +oBinaryDict.listen(); +oGenerator.listen(); Index: gc_lang/fr/tb/content/lex_editor.xul ================================================================== --- gc_lang/fr/tb/content/lex_editor.xul +++ gc_lang/fr/tb/content/lex_editor.xul @@ -6,14 +6,14 @@ @@ -21,11 +21,11 @@