import * as d3 from 'd3' ; import { d3GetEvent } from './utils' ; import * as _ from 'underscore' ; import { BaseXYSelector } from './Selector' ; import * as sel_utils from './selector_utils' ; export class LassoSelector extends BaseXYSelector { render ( ) { super . render ( ) ; const scale_creation_promise = this . create_scales ( ) ; this . line = d3 . line ( ) ; this . all_vertices = { } ; this . lasso_counter = 0 ; const that = this ; Promise . all ( [ this . mark_views_promise , scale_creation_promise ] ) . then ( ( ) => { const drag = d3 . drag ( ) . on ( 'start' , ( ) => { that . drag_start ( ) ; } ) . on ( 'drag' , ( ) => { that . drag_move ( ) ; } ) . on ( 'end' , ( ) => { that . drag_end ( ) ; } ) ; d3 . select ( window ) . on ( 'keydown' , ( ) => { this . keydown ( ) ; } ) ; that . d3el . attr ( 'class' , 'lassoselector' ) ; that . background = that . d3el . append ( 'rect' ) . attr ( 'x' , 0 ) . attr ( 'y' , 0 ) . attr ( 'width' , that . width ) . attr ( 'height' , that . height ) . attr ( 'visibility' , 'hidden' ) . attr ( 'pointer-events' , 'all' ) . style ( 'cursor' , 'crosshair' ) . call ( drag ) ; that . create_listeners ( ) ; } ) ; } create_listeners ( ) { super . create_listeners ( ) ; this . listenTo ( this . model , 'change:color' , this . change_color ) ; } change_color ( model , color ) { if ( color ) { this . d3el . selectAll ( 'path' ) . style ( 'stroke' , color ) ; } } create_new_lasso ( ) { const lasso = this . d3el . append ( 'path' ) . attr ( 'id' , 'l' + ++ this . lasso_counter ) . on ( 'click' , function ( ) { const lasso = d3 . select ( this ) ; lasso . classed ( 'selected' , ! lasso . classed ( 'selected' ) ) ; } ) ; const color = this . model . get ( 'color' ) ; if ( color ) { lasso . style ( 'stroke' , color ) ; } } drag_start ( ) { this . current_vertices = [ ] ; this . create_new_lasso ( ) ; } drag_move ( ) { this . current_vertices . push ( d3 . mouse ( this . background . node ( ) ) ) ; this . d3el . select ( '#l' + this . lasso_counter ) . attr ( 'd' , this . line ( this . current_vertices ) ) ; } drag_end ( ) { const lasso_name = 'l' + this . lasso_counter ; this . d3el . select ( '#' + lasso_name ) . attr ( 'd' , this . line ( this . current_vertices ) + 'Z' ) ; this . all_vertices [ lasso_name ] = this . current_vertices ; this . update_mark_selected ( this . all_vertices ) ; } update_mark_selected ( vertices ? ) { if ( vertices === undefined || vertices . length === 0 ) { _ . each ( this . mark_views , ( mark_view ) => { return mark_view . selector_changed ( ) ; } ) ; } const point_selector = function ( p ) { for ( const l in vertices ) { if ( sel_utils . point_in_lasso ( p , vertices [ l ] ) ) { return true ; } } return false ; } ; const rect_selector = function ( xy ) { for ( const l in vertices ) { if ( sel_utils . lasso_inter_rect ( xy [ 0 ] , xy [ 1 ] , vertices [ l ] ) ) { return true ; } } return false ; } ; _ . each ( this . mark_views , ( mark_view ) => { mark_view . selector_changed ( point_selector , rect_selector ) ; } , this ) ; } relayout ( ) { super . relayout ( ) ; this . background . attr ( 'width' , this . width ) . attr ( 'height' , this . height ) ; } keydown ( ) { if ( d3GetEvent ( ) . keyCode === 46 ) { const lassos_to_delete = this . d3el . selectAll ( '.selected' ) ; const vertices = this . all_vertices ; lassos_to_delete . each ( function ( ) { const lasso_name = d3 . select ( this ) . attr ( 'id' ) ; delete vertices [ lasso_name ] ; } ) ; lassos_to_delete . remove ( ) ; this . update_mark_selected ( this . all_vertices ) ; } } reset ( ) { this . lasso_counter = 0 ; this . all_vertices = { } ; this . d3el . selectAll ( 'path' ) . remove ( ) ; this . update_mark_selected ( ) ; } selected_changed ( ) { } line : d3 . Line < [ number , number ] > ; all_vertices : { [ key ] : [ number , number ] [ ] ; } ; lasso_counter : number ; background : d3 . Selection < SVGRectElement , any , any , any > ; current_vertices : [ number , number ] [ ] ; }