Commit ad7d31f1 authored by Romain Loth's avatar Romain Loth

fix the setState mecanism

the new variant pushState will append new states itself + SystemState becomes an accessor to TW.states[-1] + start simplifying changeType
parent 3c0e1b3c
......@@ -187,6 +187,9 @@ TW.conf = (function(TW){
// TW.geomap = false;
// TW.twittertimeline = false;
TWConf.maxPastStates = 5 ; // number of TW.states to remember (~CTRL-Z)
// Layout options
// --------------
TWConf.fa2Available=true; // show/hide fa2Button
......@@ -294,8 +297,9 @@ TW.conf = (function(TW){
// show verbose console logs...
logFetchers: false, // ...about ajax/fetching of graph data
logParsers: false, // ...about parsing said data
logFacets: true, // ...about parsing node attribute:value facets
logFacets: false, // ...about parsing node attribute:value facets
logSettings: false, // ...about settings at Tina and Sigma init time
logStates: true, // ...about TW.states array
logSelections: false
}
......
......@@ -69,7 +69,7 @@ function SelectionEngine() {
// we assume string is normalized
this.search_n_select = function(string) {
let previousSelections = TW.SystemState.selectionNids
let previousSelections = TW.SystemState().selectionNids
cancelSelection(false, {norender:true});
......@@ -147,8 +147,7 @@ function SelectionEngine() {
*
* @nodes: eg targeted array (only ids)
*
* external usage : partialGraph.states,
* updateRelatedNodesPanel();
* external usage : clickHandler, search, changeType, filters, tag click...
*/
// ====================
this.MultipleSelection2 = function(args) {
......@@ -170,7 +169,7 @@ function SelectionEngine() {
var sameSideNeighbors = {}
var oppositeSideNeighbors = {}
// TW.states.slice(-1)[0] is the present graph state
// TW.SystemState() is the present graph state
// eg
// {categories: ["someNodeCat"]
// categoriesDict: {"someNodeCat":0} // where val 0 or 1 is type sem or soc
......@@ -277,32 +276,24 @@ function SelectionEngine() {
// show the button to remove selection
$("#unselectbutton").show() ;
let theSelection = Object.keys(selections)
// £TODO: all this should be done in one line via TW.setState or ref
TW.SystemState.selectionNids = Object.keys(selections)
TW.states.slice(-1)[0].selectionNids = TW.SystemState.selectionNids;
TW.setState( { sels: TW.SystemState.selectionNids} )
if (TW.SystemState.selectionNids.length
&& TW.SystemState.selectionNids[0] == 'NaN') {
console.error("NaN selection key error")
}
// alert("MultipleSelection2=======\nthe_new_sels:" + JSON.stringify(TW.SystemState.selectionNids))
// it's a new SystemState
TW.pushState( { sels: theSelection } )
// we send our "gotNodeSet" event
// (signal for plugins that a search-selection was done or a new hand picked selection)
$('#searchinput').trigger({
type: "tw:gotNodeSet",
q: $("#searchinput").val(),
nodeIds: TW.SystemState.selectionNids
nodeIds: theSelection
});
// console.log("Event [gotNodeSet] sent from Tinaweb MultipleSelection2")
// neighbors of the opposite type
if(TW.Relations["1|1"]) {
for(var s in TW.SystemState.selectionNids) {
var bipaNeighs = TW.Relations["1|1"][TW.SystemState.selectionNids[s]];
for(var s in theSelection) {
var bipaNeighs = TW.Relations["1|1"][theSelection[s]];
for(var n in bipaNeighs) {
if (typeof oppositeSideNeighbors[bipaNeighs[n]] == "undefined")
......@@ -324,7 +315,7 @@ function SelectionEngine() {
});
if (TW.conf.debug.logSelections) {
console.debug('TW.SystemState.selectionNids', TW.SystemState.selectionNids)
console.debug('new states\'s selectionNids', theSelection)
console.debug('oppos', oppos)
console.debug('same', same)
}
......@@ -334,7 +325,7 @@ function SelectionEngine() {
TW.partialGraph.render();
updateRelatedNodesPanel( TW.SystemState.selectionNids , same, oppos )
updateRelatedNodesPanel( theSelection , same, oppos )
if (TW.conf.debug.logSelections) {
var tMS2_fin = performance.now()
......@@ -831,7 +822,7 @@ var TinaWebJS = function ( sigmacanvas ) {
var targeted = selInst.SelectorEngine( {
addvalue:TW.gui.checkBox,
currsels:circleNodes,
prevsels:TW.SystemState.selectionNids
prevsels:TW.SystemState().selectionNids
} )
// 2) clear previous selection
......@@ -847,7 +838,7 @@ var TinaWebJS = function ( sigmacanvas ) {
// when one node and normal click
// ===============================
partialGraph.bind('clickNode', function(e) {
// console.log("clickNode event e", e.data.node)
console.log("clickNode event e", e.data.node)
// new sigma.js gives easy access to clicked node!
var theNodeId = e.data.node.id
......@@ -857,10 +848,10 @@ var TinaWebJS = function ( sigmacanvas ) {
var targeted = selInst.SelectorEngine( {
addvalue:TW.gui.checkBox,
currsels:[theNodeId],
prevsels: TW.SystemState.selectionNids
prevsels: TW.SystemState().selectionNids
} )
// 2)
cancelSelection(false, {norender:true}); // no need to render before MS2
// cancelSelection(false, {norender:true}); // no need to render before MS2
// 3)
if(targeted.length>0) {
selInst.MultipleSelection2( {nodes:targeted} )
......@@ -1040,7 +1031,9 @@ var TinaWebJS = function ( sigmacanvas ) {
if (TW.partialGraph && TW.partialGraph.graph) {
TW.partialGraph.graph.clear()
TW.partialGraph.refresh()
TW.SystemState.selectionNids = []
// ££TODO push state
TW.SystemState().selectionNids = []
}
}
......
......@@ -191,11 +191,8 @@ function createFilechooserEl () {
// Documentation Level: *****
function changeType() {
var present = TW.states.slice(-1)[0]; // Last
var past = TW.states.slice(-2)[0] // avant Last
var lastpos = TW.states.length-1;
var avantlastpos = lastpos-1;
var present = TW.SystemState() ; // current state before the change
var level = present.level;
var sels = present.selectionNids
......@@ -229,15 +226,8 @@ function changeType() {
if(level) nextState = t1Activetypes;
else nextState = binSumCats;
if(!level && past!=false) {
var sum_past = present.activetypes.map(Number).reduce(function(a, b){return a+b;})
console.log("sum_past:")
console.log(sum_past)
console.log("past.activetypes:")
console.log(past.activetypes)
if(sum_past>1) {
nextState = past.activetypes;
}
if(!level && t0ActivetypesKey == '1|1') {
nextState = [true, false];
}
var str_nextState = nextState.map(Number).join("|")
......@@ -289,15 +279,6 @@ function changeType() {
}
} else /* Local level, change to previous or alter component*/ {
if(sels.length==0) {
console.log(" * * * * * * * * * * * * * * ")
console.log("the past: ")
console.log(past.activetypes.map(Number)+" , "+past.level)
console.log(past)
console.log("the present: ")
console.log(present.activetypes.map(Number)+" , "+present.level)
console.log(present)
console.log("t0ActivetypesKey: "+t0ActivetypesKey)
console.log("t1ActivetypesKey: "+t1ActivetypesKey)
console.log("str_nextState: "+str_nextState)
......@@ -355,8 +336,6 @@ function changeType() {
var sumFutureCats = nextState.map(Number).reduce(function(a, b){return a+b;})
nextState = (sumFutureCats==2 && !level && sumCats==1 )? nextState : t1Activetypes;
if(t1ActivetypesKey=="0|0" ) nextState=past.activetypes;
// nextState = ( past.activetypes && !level && sumCats==1 )? past.activetypes : t1Activetypes;
str_nextState = nextState.map(Number).join("|")
var sumNextState = nextState.map(Number).reduce(function(a, b){return a+b;})
......@@ -442,17 +421,10 @@ function changeType() {
TW.gui.selectionActive=true;
}
// £TODO this should be done by setState()
TW.states[avantlastpos] = {};
TW.states[avantlastpos].LouvainFait = false;
TW.states[avantlastpos].level = present.level;
TW.states[avantlastpos].selectionNids = selsbackup;
TW.states[avantlastpos].activetypes = present.activetypes;
// possible: integrated highlighted opposite- and same-side neighbours from MS2
// (var used to exist but wasn't filled and used consistently)
TW.setState({
TW.pushState({
activetypes: nextState,
level: level,
sels: sels,
oppos: []
})
......@@ -487,12 +459,8 @@ function changeLevel() {
// let the waiting cursor appear
setTimeout(function() {
var present = TW.states.slice(-1)[0]; // Last
var past = TW.states.slice(-2)[0] // avant Last
var lastpos = TW.states.length-1;
var avantlastpos = lastpos-1;
var present = TW.SystemState(); // Last
var level = present.level;
var sels = present.selectionNids ;//[144, 384, 543]//TW.states[last].selectionNids;
let selsChecker = {}
......@@ -506,13 +474,8 @@ function changeLevel() {
// types eg [true] <=> '1'
// [true, true] <=> '1|1'
var t0Activetypes = present.activetypes;
var t0ActivetypesKey = t0Activetypes.map(Number).join("|")
// [X|Y]-change (NOT operation over the received state [X\Y] )
var t1Activetypes = []
for(var i in t0Activetypes) t1Activetypes[i] = !t0Activetypes[i]
var t1ActivetypesKey = t1Activetypes.map(Number).join("|")
var activetypes = present.activetypes;
var activetypesKey = activetypes.map(Number).join("|")
TW.partialGraph.graph.clear();
......@@ -524,7 +487,7 @@ function changeLevel() {
// POSS: factorize with same strategy in MultipleSelection2 beginning
for(var i in sels) {
s = sels[i];
neigh = TW.Relations[t0ActivetypesKey][s]
neigh = TW.Relations[activetypesKey][s]
if(neigh) {
for(var j in neigh) {
t = neigh[j]
......@@ -540,7 +503,7 @@ function changeLevel() {
nodes_2_colour[sels[i]]=true;
var futurelevel = []
var futurelevel = null
if(present.level) { // [Change to Local] when level=Global(1)
for(var nid in nodes_2_colour)
......@@ -568,12 +531,12 @@ function changeLevel() {
// var t0 = performance.now()
for(var nid in TW.Nodes) {
if(t0Activetypes[TW.catDict[TW.Nodes[nid].type]])
if(activetypes[TW.catDict[TW.Nodes[nid].type]])
// we add 1 by 1
add1Elem(nid)
}
for(var eid in TW.Edges) {
if(TW.Edges[eid].categ==t0ActivetypesKey)
if(TW.Edges[eid].categ == activetypesKey)
add1Elem(eid)
}
......@@ -593,17 +556,8 @@ function changeLevel() {
}
}
// console.log("enviroment changeLevel nodes_2_colour", nodes_2_colour)
TW.states[avantlastpos] = {};
TW.states[avantlastpos].level = present.level;
TW.states[avantlastpos].activetypes = present.activetypes;
TW.states[avantlastpos].selectionNids = present.selectionNids;
TW.setState({
activetypes: present.activetypes,
level: futurelevel,
sels: sels,
oppos: []
TW.pushState({
level: futurelevel
})
TW.partialGraph.camera.goTo({x:0, y:0, ratio:1.2, angle: 0})
......
......@@ -15,17 +15,21 @@ TW.gexfPaths={}; // for file selectors iff servermenu
TW.categories = []; // possible node types and their inverted map
TW.catDict = {};
// SystemState is a summary of current situation
TW.SystemState = {}
TW.SystemState.activetypes = [] // <== filled from TW.categories
TW.SystemState.level = true;
TW.SystemState.selectionNids = []; // <== current selection !!
TW.SystemState.LouvainFait = false;
// states[] is an array of SystemStates for future CTRL+Z or usage track
TW.states = []
TW.states[0] = false;
TW.states[1] = TW.SystemState
// a system state is the summary of tina situation
TW.initialSystemState = {
activetypes: [], // <== filled from TW.categories
level: true,
selectionNids: [], // <== current selection !!
LouvainFait: false,
id: 0 // simple incremental stateid
}
// states[] is an array of system states for future CTRL+Z or usage track
TW.states = [TW.initialSystemState]
// SystemState() returns the current situation
TW.SystemState = function() { return TW.states.slice(-1)[0] }
// -------------------------------8<--------------
// £TODO remove deprecated here and in parseCustom
......@@ -357,7 +361,7 @@ function mainStartGraph(inFormat, inData, twInstance) {
var possibleActivetypes = TW.instance.allPossibleActivetypes( TW.categories )
// remember it
TW.states[1].activetypes = initialActivetypes ;
TW.pushState({'activetypes': initialActivetypes})
// XML parsing from ParseCustom
var dicts = start.makeDicts(TW.categories); // > parse json or gexf, dictfy
......
......@@ -5,47 +5,44 @@
// ex: new selections: {sels: [268]}
// ex: new activetypes: {activetypes:[false, true]}
// ex: new level: {level:false}
TW.setState = function( args ) {
var bistate=false, typesKey=false;
TW.pushState = function( args ) {
// £TODO we could append the new state in this function too
var present = TW.states.slice(-1)[0]; // Last
var past = TW.states.slice(-2)[0] // avant Last
let lastState = TW.states.slice(-1)[0] // <=> TW.SystemState()
if (TW.conf.debug.logSelections) console.log("setState args: ", args);
if(!isUndef(args.activetypes)) {
// 1) we start from a copy
let newState = Object.assign({}, lastState)
// record into last state
present.activetypes = args.activetypes;
// counter à toutes fins utiles
newState.id ++
// 2) we update it with provided args
if (!isUndef(args.sels)) newState.selectionNids = args.sels;
if (!isUndef(args.activetypes)) newState.activetypes = args.activetypes
if (!isUndef(args.level)) newState.level = args.level;
bistate= present.activetypes.map(Number).reduce(
function(a, b){return a+b;}
)
typesKey = present.activetypes.map(Number).join("|")
}
// console.log("printing the typesKey:", typesKey)
// POSS1: add neighbors (of both types) in a .neighborsNids[type] slot
// POSS2: add filterSliders params to be able to recreate subsets at a given time
if(!isUndef(args.level)) present.level = args.level;
if(!isUndef(args.sels)) present.selectionNids = args.sels;
present.LouvainFait = false;
// useful shortcut
let typesKey = newState.activetypes.map(Number).join("|")
// change level needs a selection
LevelButtonDisable(false); // £TODO rename toggleLevelButton
if( present.level
&& present.selectionNids
&& present.selectionNids.length==0)
LevelButtonDisable(true);
// legacy : we prefer to redo louvain than to miss a new nodeset
// (wouldn't be needed if POSS2 implemented)
newState.LouvainFait = false;
// 3) apply all GUI effects
// case to go back
if(present.level==false && bistate>1)
LevelButtonDisable(true)
// change level depends on a selection
LevelButtonDisable( (newState.selectionNids.length == 0) );
// recreate sliders after activetype or level changes
if (TW.conf.filterSliders
&& (present.level != past.level
|| present.activetypes.map(Number).join("|") != past.activetypes.map(Number).join("|"))) {
&& (newState.level != lastState.level
|| typesKey != lastState.activetypes.map(Number).join("|"))) {
// terms
if(typesKey=="0|1") {
......@@ -77,9 +74,20 @@ TW.setState = function( args ) {
}
}
// 4) store it in TW.states
TW.states.push(newState)
// 5) forget oldest states if needed
while (TW.states.length > TW.conf.maxPastStates) {
TW.states.shift()
}
if (TW.conf.debug.logStates)
console.log(`updated states: ${JSON.stringify(TW.states)}`)
};
TW.resetGraph = function() {
// call the sigma graph clearing
TW.instance.clearSigma()
......@@ -88,6 +96,8 @@ TW.resetGraph = function() {
// reset remaining global vars
TW.labels = []
TW.Relations = {}
TW.states = [TW.initialSystemState]
// reset rendering gui flags
TW.gui.selectionActive = false
......@@ -111,7 +121,9 @@ function cancelSelection (fromTagCloud, settings) {
highlightSelectedNodes(false); //Unselect the selected ones :D
// clear the current state's selection and neighbors arrays
TW.SystemState.selectionNids.splice(0, TW.SystemState.selectionNids.length)
// new state
TW.pushState({sels:[]})
// global flag
TW.gui.selectionActive = false
......@@ -228,10 +240,11 @@ function swActual(aNodetype) {
function highlightSelectedNodes(flag){
let sels = TW.SystemState().selectionNids
if (TW.conf.debug.logSelections)
console.log("\t***methods.js:highlightSelectedNodes(flag)"+flag+" sel:"+TW.SystemState.selectionNids)
for(let i in TW.SystemState.selectionNids) {
let nid = TW.SystemState.selectionNids[i]
console.log("\t***methods.js:highlightSelectedNodes(flag)"+flag+" sel:"+sels)
for(let i in sels) {
let nid = sels[i]
TW.partialGraph.graph.nodes(nid).active = flag
}
}
......
......@@ -630,8 +630,9 @@ function getNodeLabels(elems){
function getSelections(){
let selLabels=[];
for(let i in TW.SystemState.selectionNids){
let nid = TW.SystemState.selectionNids[i]
let sels = TW.SystemState().selectionNids
for(let i in sels ){
let nid = sels[i]
selLabels.push(TW.Nodes[nid].label);
}
return selLabels;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment