@@ -17,6 +17,8 @@ var Axes = require('../../plots/cartesian/axes');
1717var Color = require ( '../color' ) ;
1818var Drawing = require ( '../drawing' ) ;
1919
20+ var dragElement = require ( '../dragelement' ) ;
21+ var setCursor = require ( '../../lib/setcursor' ) ;
2022
2123var shapes = module . exports = { } ;
2224
@@ -299,15 +301,7 @@ function updateShape(gd, index, opt, value) {
299301 var options = handleShapeDefaults ( optionsIn , gd . _fullLayout ) ;
300302 gd . _fullLayout . shapes [ index ] = options ;
301303
302- var attrs = {
303- 'data-index' : index ,
304- 'fill-rule' : 'evenodd' ,
305- d : shapePath ( gd , options )
306- } ,
307- clipAxes ;
308-
309- var lineColor = options . line . width ? options . line . color : 'rgba(0,0,0,0)' ;
310-
304+ var clipAxes ;
311305 if ( options . layer !== 'below' ) {
312306 clipAxes = ( options . xref + options . yref ) . replace ( / p a p e r / g, '' ) ;
313307 drawShape ( gd . _fullLayout . _shapeUpperLayer ) ;
@@ -332,6 +326,14 @@ function updateShape(gd, index, opt, value) {
332326 }
333327
334328 function drawShape ( shapeLayer ) {
329+ var attrs = {
330+ 'data-index' : index ,
331+ 'fill-rule' : 'evenodd' ,
332+ d : shapePath ( gd , options )
333+ } ,
334+ lineColor = options . line . width ?
335+ options . line . color : 'rgba(0,0,0,0)' ;
336+
335337 var path = shapeLayer . append ( 'path' )
336338 . attr ( attrs )
337339 . style ( 'opacity' , options . opacity )
@@ -343,6 +345,72 @@ function updateShape(gd, index, opt, value) {
343345 path . call ( Drawing . setClipUrl ,
344346 'clip' + gd . _fullLayout . _uid + clipAxes ) ;
345347 }
348+
349+ if ( ! gd . _context . editable ) return ;
350+
351+ var update ;
352+ var x0 , y0 , x1 , y1 , astrX0 , astrY0 , astrX1 , astrY1 ;
353+ var pathIn , astrPath ;
354+ var xa , ya , x2p , y2p , p2x , p2y ;
355+ dragElement . init ( {
356+ element : path . node ( ) ,
357+ prepFn : function ( ) {
358+ setCursor ( path , 'move' ) ;
359+
360+ xa = Axes . getFromId ( gd , options . xref ) ;
361+ ya = Axes . getFromId ( gd , options . yref ) ;
362+
363+ x2p = getDataToPixel ( gd , xa ) ;
364+ y2p = getDataToPixel ( gd , ya , true ) ;
365+ p2x = getPixelToData ( gd , xa ) ;
366+ p2y = getPixelToData ( gd , ya , true ) ;
367+
368+ var astr = 'shapes[' + index + ']' ;
369+ if ( options . type === 'path' ) {
370+ pathIn = options . path ;
371+ astrPath = astr + '.path' ;
372+ }
373+ else {
374+ x0 = x2p ( options . x0 ) ;
375+ y0 = y2p ( options . y0 ) ;
376+ x1 = x2p ( options . x1 ) ;
377+ y1 = y2p ( options . y1 ) ;
378+
379+ astrX0 = astr + '.x0' ;
380+ astrY0 = astr + '.y0' ;
381+ astrX1 = astr + '.x1' ;
382+ astrY1 = astr + '.y1' ;
383+ }
384+
385+ update = { } ;
386+ } ,
387+ moveFn : function ( dx , dy ) {
388+ if ( options . type === 'path' ) {
389+ var moveX = function moveX ( x ) { return p2x ( x2p ( x ) + dx ) ; } ;
390+ if ( xa && xa . type === 'date' ) moveX = encodeDate ( moveX ) ;
391+
392+ var moveY = function moveY ( y ) { return p2y ( y2p ( y ) + dy ) ; } ;
393+ if ( ya && ya . type === 'date' ) moveY = encodeDate ( moveY ) ;
394+
395+ options . path = movePath ( pathIn , moveX , moveY ) ;
396+ update [ astrPath ] = options . path ;
397+ }
398+ else {
399+ update [ astrX0 ] = options . x0 = p2x ( x0 + dx ) ;
400+ update [ astrY0 ] = options . y0 = p2y ( y0 + dy ) ;
401+ update [ astrX1 ] = options . x1 = p2x ( x1 + dx ) ;
402+ update [ astrY1 ] = options . y1 = p2y ( y1 + dy ) ;
403+ }
404+
405+ path . attr ( 'd' , shapePath ( gd , options ) ) ;
406+ } ,
407+ doneFn : function ( dragged ) {
408+ setCursor ( path ) ;
409+ if ( dragged ) {
410+ Plotly . relayout ( gd , update ) ;
411+ }
412+ }
413+ } ) ;
346414 }
347415}
348416
@@ -375,6 +443,51 @@ function decodeDate(convertToPx) {
375443 return function ( v ) { return convertToPx ( v . replace ( '_' , ' ' ) ) ; } ;
376444}
377445
446+ function encodeDate ( convertToDate ) {
447+ return function ( v ) { return convertToDate ( v ) . replace ( ' ' , '_' ) ; } ;
448+ }
449+
450+ function getDataToPixel ( gd , axis , isVertical ) {
451+ var gs = gd . _fullLayout . _size ,
452+ dataToPixel ;
453+
454+ if ( axis ) {
455+ var d2l = dataToLinear ( axis ) ;
456+
457+ dataToPixel = function ( v ) {
458+ return axis . _offset + axis . l2p ( d2l ( v , true ) ) ;
459+ } ;
460+
461+ if ( axis . type === 'date' ) dataToPixel = decodeDate ( dataToPixel ) ;
462+ }
463+ else if ( isVertical ) {
464+ dataToPixel = function ( v ) { return gs . t + gs . h * ( 1 - v ) ; } ;
465+ }
466+ else {
467+ dataToPixel = function ( v ) { return gs . l + gs . w * v ; } ;
468+ }
469+
470+ return dataToPixel ;
471+ }
472+
473+ function getPixelToData ( gd , axis , isVertical ) {
474+ var gs = gd . _fullLayout . _size ,
475+ pixelToData ;
476+
477+ if ( axis ) {
478+ var l2d = linearToData ( axis ) ;
479+ pixelToData = function ( p ) { return l2d ( axis . p2l ( p - axis . _offset ) ) ; } ;
480+ }
481+ else if ( isVertical ) {
482+ pixelToData = function ( p ) { return 1 - ( p - gs . t ) / gs . h ; } ;
483+ }
484+ else {
485+ pixelToData = function ( p ) { return ( p - gs . l ) / gs . w ; } ;
486+ }
487+
488+ return pixelToData ;
489+ }
490+
378491function shapePath ( gd , options ) {
379492 var type = options . type ,
380493 xa = Axes . getFromId ( gd , options . xref ) ,
@@ -501,6 +614,29 @@ shapes.convertPath = function(pathIn, x2p, y2p) {
501614 } ) ;
502615} ;
503616
617+ function movePath ( pathIn , moveX , moveY ) {
618+ return pathIn . replace ( segmentRE , function ( segment ) {
619+ var paramNumber = 0 ,
620+ segmentType = segment . charAt ( 0 ) ,
621+ xParams = paramIsX [ segmentType ] ,
622+ yParams = paramIsY [ segmentType ] ,
623+ nParams = numParams [ segmentType ] ;
624+
625+ var paramString = segment . substr ( 1 ) . replace ( paramRE , function ( param ) {
626+ if ( paramNumber >= nParams ) return param ;
627+
628+ if ( xParams [ paramNumber ] ) param = moveX ( param ) ;
629+ else if ( yParams [ paramNumber ] ) param = moveY ( param ) ;
630+
631+ paramNumber ++ ;
632+
633+ return param ;
634+ } ) ;
635+
636+ return segmentType + paramString ;
637+ } ) ;
638+ }
639+
504640shapes . calcAutorange = function ( gd ) {
505641 var fullLayout = gd . _fullLayout ,
506642 shapeList = fullLayout . shapes ,
0 commit comments