Skip to content

Commit 22e8c7e

Browse files
committed
Make default splom selection
1 parent e14013b commit 22e8c7e

File tree

3 files changed

+160
-40
lines changed

3 files changed

+160
-40
lines changed

src/traces/scattergl/convert.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ function convertStyle(gd, trace) {
5050
opts.unselected.opacity[i] = DESELECTDIM * mo[i];
5151
}
5252
}
53+
54+
// FIXME: if only trace.selected provided, trace.unselected remains empty
55+
// cc @etienne
5356
}
5457

5558
if(subTypes.hasLines(trace)) {
@@ -402,6 +405,7 @@ function convertErrorBarPositions(gd, trace, positions) {
402405
module.exports = {
403406
convertStyle: convertStyle,
404407
convertMarkerStyle: convertMarkerStyle,
408+
convertMarkerSelection: convertMarkerSelection,
405409
convertLinePositions: convertLinePositions,
406410
convertErrorBarPositions: convertErrorBarPositions
407411
};

src/traces/splom/base_plot.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,13 @@ function drag(gd) {
6161
}
6262
}
6363

64-
scene.matrix.update({ranges: ranges});
65-
scene.matrix.draw();
64+
if(scene.selectBatch) {
65+
scene.matrix.update({ranges: ranges}, {ranges: ranges});
66+
scene.matrix.draw(scene.unselectBatch, scene.selectBatch);
67+
} else {
68+
scene.matrix.update({ranges: ranges});
69+
scene.matrix.draw();
70+
}
6671
}
6772
}
6873

src/traces/splom/index.js

Lines changed: 149 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,16 @@
99
'use strict';
1010

1111
var createMatrix = require('regl-scattermatrix');
12+
var arrayRange = require('array-range');
1213

1314
var Lib = require('../../lib');
1415
var AxisIDs = require('../../plots/cartesian/axis_ids');
1516

17+
var subTypes = require('../scatter/subtypes');
1618
var calcMarkerSize = require('../scatter/calc').calcMarkerSize;
1719
var calcAxisExpansion = require('../scatter/calc').calcAxisExpansion;
1820
var calcColorscales = require('../scatter/colorscale_calc');
21+
var convertMarkerSelection = require('../scattergl/convert').convertMarkerSelection;
1922
var convertMarkerStyle = require('../scattergl/convert').convertMarkerStyle;
2023
var calcHover = require('../scattergl').calcHover;
2124

@@ -75,6 +78,9 @@ function calc(gd, trace) {
7578
if(!scene.matrix) scene.matrix = true;
7679
scene.matrixOptions = opts;
7780

81+
scene.selectedOptions = convertMarkerSelection(trace, trace.selected);
82+
scene.unselectedOptions = convertMarkerSelection(trace, trace.unselected);
83+
7884
return [{x: false, y: false, t: stash, trace: trace}];
7985
}
8086

@@ -118,18 +124,16 @@ function sceneUpdate(gd, stash) {
118124
if(!scene) {
119125
scene = stash._scene = Lib.extendFlat({}, reset, first);
120126

121-
// TODO should we use something like this on drag?
122-
scene.update = function update(opt) {
123-
if(scene.matrix) scene.matrix.update(opt);
124-
scene.draw();
125-
};
126-
127127
scene.draw = function draw() {
128-
if(scene.matrix) scene.matrix.draw();
128+
// draw traces in selection mode
129+
if(scene.matrix && scene.selectBatch) {
130+
scene.matrix.draw(scene.unselectBatch, scene.selectBatch);
131+
}
129132

130-
// TODO selection stuff
133+
else if(scene.matrix) {
134+
scene.matrix.draw();
135+
}
131136

132-
// do we need to use this flag anywhere??
133137
scene.dirty = false;
134138
};
135139

@@ -143,7 +147,7 @@ function sceneUpdate(gd, stash) {
143147
if(!scene.selectBatch) return;
144148
scene.selectBatch = null;
145149
scene.unselectBatch = null;
146-
scene.matrix.update(scene.opts);
150+
scene.matrix.update(scene.matrixOptions);
147151
scene.clear();
148152
scene.draw();
149153
};
@@ -152,7 +156,7 @@ function sceneUpdate(gd, stash) {
152156
scene.destroy = function destroy() {
153157
if(scene.matrix) scene.matrix.destroy();
154158

155-
scene.opts = null;
159+
scene.matrixOptions = null;
156160
scene.selectBatch = null;
157161
scene.unselectBatch = null;
158162

@@ -180,29 +184,30 @@ function plotOne(gd, cd0) {
180184
var fullLayout = gd._fullLayout;
181185
var gs = fullLayout._size;
182186
var trace = cd0.trace;
183-
var scene = cd0.t._scene;
184-
var opts = scene.matrixOptions;
185-
var matrix = opts.data;
187+
var stash = cd0.t;
188+
var scene = stash._scene;
189+
var matrixData = scene.matrixOptions.data;
186190
var regl = fullLayout._glcanvas.data()[0].regl;
191+
var dragmode = fullLayout.dragmode;
187192

188-
if(matrix.length === 0) return;
193+
if(matrixData.length === 0) return;
189194

190-
var k = 0;
195+
var k = 0, i;
191196
var activeLength = trace._activeLength;
192-
var visibleLength = matrix.length;
197+
var visibleLength = matrixData.length;
193198
var viewOpts = {
194199
ranges: new Array(visibleLength),
195200
domains: new Array(visibleLength)
196201
};
197202

198203
for(var i = 0; i < activeLength; i++) {
199-
if(trace.dimensions[i].visible) {
200-
var xa = AxisIDs.getFromId(gd, trace.xaxes[i]);
201-
var ya = AxisIDs.getFromId(gd, trace.yaxes[i]);
202-
viewOpts.ranges[k] = [xa.range[0], ya.range[0], xa.range[1], ya.range[1]];
203-
viewOpts.domains[k] = [xa.domain[0], ya.domain[0], xa.domain[1], ya.domain[1]];
204-
k++;
205-
}
204+
if(!trace.dimensions[i].visible) continue;
205+
206+
var xa = AxisIDs.getFromId(gd, trace.xaxes[i]);
207+
var ya = AxisIDs.getFromId(gd, trace.yaxes[i]);
208+
viewOpts.ranges[k] = [xa.range[0], ya.range[0], xa.range[1], ya.range[1]];
209+
viewOpts.domains[k] = [xa.domain[0], ya.domain[0], xa.domain[1], ya.domain[1]];
210+
k++;
206211
}
207212

208213
viewOpts.viewport = [gs.l, gs.b, gs.w + gs.l, gs.h + gs.b];
@@ -211,10 +216,60 @@ function plotOne(gd, cd0) {
211216
scene.matrix = createMatrix(regl);
212217
}
213218

214-
// FIXME: generate multiple options for single update
215-
scene.matrix.update(opts);
216-
scene.matrix.update(viewOpts);
217-
scene.matrix.draw();
219+
var selectMode = dragmode === 'lasso' || dragmode === 'select' || !!trace.selectedpoints;
220+
scene.selectBatch = null;
221+
scene.unselectBatch = null;
222+
223+
if(selectMode) {
224+
if(!scene.selectBatch) {
225+
scene.selectBatch = [];
226+
scene.unselectBatch = [];
227+
}
228+
229+
// regenerate scene batch, if traces number changed during selection
230+
if(trace.selectedpoints) {
231+
scene.selectBatch = trace.selectedpoints;
232+
233+
var selPts = trace.selectedpoints;
234+
var selDict = {};
235+
for(i = 0; i < selPts.length; i++) {
236+
selDict[selPts[i]] = true;
237+
}
238+
var unselPts = [];
239+
for(i = 0; i < matrixData[0].length; i++) {
240+
if(!selDict[i]) unselPts.push(i);
241+
}
242+
scene.unselectBatch = unselPts;
243+
}
244+
245+
// precalculate px coords since we are not going to pan during select
246+
// var xpx = new Array(stash.count);
247+
// var ypx = new Array(stash.count);
248+
// for(i = 0; i < stash.count; i++) {
249+
// xpx[i] = xaxis.c2p(x[i]);
250+
// ypx[i] = yaxis.c2p(y[i]);
251+
// }
252+
// stash.xpx = xpx;
253+
// stash.ypx = ypx;
254+
255+
256+
if(scene.selectBatch) {
257+
scene.matrix.update(scene.matrixOptions, scene.matrixOptions);
258+
scene.matrix.update(scene.unselectedOptions, scene.selectedOptions);
259+
scene.matrix.update(viewOpts, viewOpts);
260+
}
261+
else {
262+
// delete selection pass
263+
scene.matrix.update(viewOpts, null);
264+
}
265+
}
266+
else {
267+
scene.matrix.update(scene.matrixOptions);
268+
scene.matrix.update(viewOpts);
269+
stash.xpx = stash.ypx = null;
270+
}
271+
272+
scene.draw();
218273
}
219274

220275
// TODO splom 'needs' the grid component, register it here?
@@ -266,17 +321,73 @@ function hoverPoints(pointData, xval, yval) {
266321
}
267322

268323
function selectPoints(searchInfo, polygon) {
269-
// var cd = searchInfo.cd;
270-
// var selection = [];
271-
// var trace = cd[0].trace;
272-
// var stash = cd[0].t;
273-
// var x = stash.x;
274-
// var y = stash.y;
275-
// var scene = stash.scene;
276-
277-
return [];
324+
var cd = searchInfo.cd;
325+
var selection = [];
326+
var trace = cd[0].trace;
327+
var stash = cd[0].t;
328+
var x = stash.x;
329+
var y = stash.y;
330+
var scene = stash._scene;
331+
332+
if(!scene) return selection;
333+
334+
var hasOnlyLines = (!subTypes.hasMarkers(trace) && !subTypes.hasText(trace));
335+
if(trace.visible !== true || hasOnlyLines) return selection;
336+
337+
// degenerate polygon does not enable selection
338+
// filter out points by visible scatter ones
339+
var els = null;
340+
var unels = null;
341+
var i;
342+
if(polygon !== false && !polygon.degenerate) {
343+
els = [], unels = [];
344+
for(i = 0; i < stash.count; i++) {
345+
if(polygon.contains([stash.xpx[i], stash.ypx[i]])) {
346+
els.push(i);
347+
selection.push({
348+
pointNumber: i,
349+
x: x[i],
350+
y: y[i]
351+
});
352+
}
353+
else {
354+
unels.push(i);
355+
}
356+
}
357+
} else {
358+
unels = arrayRange(stash.count);
359+
}
360+
361+
// make sure selectBatch is created
362+
if(!scene.selectBatch) {
363+
scene.selectBatch = [];
364+
scene.unselectBatch = [];
365+
}
366+
367+
if(!scene.selectBatch) {
368+
// enter every trace select mode
369+
for(i = 0; i < scene.count; i++) {
370+
scene.selectBatch = [];
371+
scene.unselectBatch = [];
372+
}
373+
// we should turn scatter2d into unselected once we have any points selected
374+
scene.matrix.update(scene.unselectedOptions);
375+
}
376+
377+
scene.selectBatch = els;
378+
scene.unselectBatch = unels;
379+
380+
return selection;
278381
}
279382

383+
function style(gd, cd) {
384+
if(cd) {
385+
var stash = cd[0].t;
386+
var scene = stash._scene;
387+
scene.clear();
388+
scene.draw();
389+
}
390+
}
280391

281392
module.exports = {
282393
moduleType: 'trace',
@@ -292,7 +403,7 @@ module.exports = {
292403
plot: plot,
293404
hoverPoints: hoverPoints,
294405
selectPoints: selectPoints,
295-
style: function() {},
406+
style: style,
296407

297408
meta: {
298409
description: [

0 commit comments

Comments
 (0)