9
9
'use strict' ;
10
10
11
11
var createMatrix = require ( 'regl-scattermatrix' ) ;
12
+ var arrayRange = require ( 'array-range' ) ;
12
13
13
14
var Lib = require ( '../../lib' ) ;
14
15
var AxisIDs = require ( '../../plots/cartesian/axis_ids' ) ;
15
16
17
+ var subTypes = require ( '../scatter/subtypes' ) ;
16
18
var calcMarkerSize = require ( '../scatter/calc' ) . calcMarkerSize ;
17
19
var calcAxisExpansion = require ( '../scatter/calc' ) . calcAxisExpansion ;
18
20
var calcColorscales = require ( '../scatter/colorscale_calc' ) ;
21
+ var convertMarkerSelection = require ( '../scattergl/convert' ) . convertMarkerSelection ;
19
22
var convertMarkerStyle = require ( '../scattergl/convert' ) . convertMarkerStyle ;
20
23
var calcHover = require ( '../scattergl' ) . calcHover ;
21
24
@@ -75,6 +78,9 @@ function calc(gd, trace) {
75
78
if ( ! scene . matrix ) scene . matrix = true ;
76
79
scene . matrixOptions = opts ;
77
80
81
+ scene . selectedOptions = convertMarkerSelection ( trace , trace . selected ) ;
82
+ scene . unselectedOptions = convertMarkerSelection ( trace , trace . unselected ) ;
83
+
78
84
return [ { x : false , y : false , t : stash , trace : trace } ] ;
79
85
}
80
86
@@ -118,18 +124,16 @@ function sceneUpdate(gd, stash) {
118
124
if ( ! scene ) {
119
125
scene = stash . _scene = Lib . extendFlat ( { } , reset , first ) ;
120
126
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
-
127
127
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
+ }
129
132
130
- // TODO selection stuff
133
+ else if ( scene . matrix ) {
134
+ scene . matrix . draw ( ) ;
135
+ }
131
136
132
- // do we need to use this flag anywhere??
133
137
scene . dirty = false ;
134
138
} ;
135
139
@@ -143,7 +147,7 @@ function sceneUpdate(gd, stash) {
143
147
if ( ! scene . selectBatch ) return ;
144
148
scene . selectBatch = null ;
145
149
scene . unselectBatch = null ;
146
- scene . matrix . update ( scene . opts ) ;
150
+ scene . matrix . update ( scene . matrixOptions ) ;
147
151
scene . clear ( ) ;
148
152
scene . draw ( ) ;
149
153
} ;
@@ -152,7 +156,7 @@ function sceneUpdate(gd, stash) {
152
156
scene . destroy = function destroy ( ) {
153
157
if ( scene . matrix ) scene . matrix . destroy ( ) ;
154
158
155
- scene . opts = null ;
159
+ scene . matrixOptions = null ;
156
160
scene . selectBatch = null ;
157
161
scene . unselectBatch = null ;
158
162
@@ -180,29 +184,30 @@ function plotOne(gd, cd0) {
180
184
var fullLayout = gd . _fullLayout ;
181
185
var gs = fullLayout . _size ;
182
186
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 ;
186
190
var regl = fullLayout . _glcanvas . data ( ) [ 0 ] . regl ;
191
+ var dragmode = fullLayout . dragmode ;
187
192
188
- if ( matrix . length === 0 ) return ;
193
+ if ( matrixData . length === 0 ) return ;
189
194
190
- var k = 0 ;
195
+ var k = 0 , i ;
191
196
var activeLength = trace . _activeLength ;
192
- var visibleLength = matrix . length ;
197
+ var visibleLength = matrixData . length ;
193
198
var viewOpts = {
194
199
ranges : new Array ( visibleLength ) ,
195
200
domains : new Array ( visibleLength )
196
201
} ;
197
202
198
203
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 ++ ;
206
211
}
207
212
208
213
viewOpts . viewport = [ gs . l , gs . b , gs . w + gs . l , gs . h + gs . b ] ;
@@ -211,10 +216,60 @@ function plotOne(gd, cd0) {
211
216
scene . matrix = createMatrix ( regl ) ;
212
217
}
213
218
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 ( ) ;
218
273
}
219
274
220
275
// TODO splom 'needs' the grid component, register it here?
@@ -266,17 +321,73 @@ function hoverPoints(pointData, xval, yval) {
266
321
}
267
322
268
323
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 ;
278
381
}
279
382
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
+ }
280
391
281
392
module . exports = {
282
393
moduleType : 'trace' ,
@@ -292,7 +403,7 @@ module.exports = {
292
403
plot : plot ,
293
404
hoverPoints : hoverPoints ,
294
405
selectPoints : selectPoints ,
295
- style : function ( ) { } ,
406
+ style : style ,
296
407
297
408
meta : {
298
409
description : [
0 commit comments