10
10
'use strict' ;
11
11
12
12
var d3 = require ( 'd3' ) ;
13
- var isNumeric = require ( 'fast-isnumeric' ) ;
14
13
15
14
var Plotly = require ( '../../plotly' ) ;
16
15
var Plots = require ( '../../plots/plots' ) ;
@@ -22,8 +21,6 @@ var svgTextUtils = require('../../lib/svg_text_utils');
22
21
var setCursor = require ( '../../lib/setcursor' ) ;
23
22
var dragElement = require ( '../dragelement' ) ;
24
23
25
- var handleAnnotationDefaults = require ( './annotation_defaults' ) ;
26
- var supplyLayoutDefaults = require ( './defaults' ) ;
27
24
var drawArrowHead = require ( './draw_arrow_head' ) ;
28
25
29
26
@@ -41,6 +38,9 @@ module.exports = {
41
38
drawOne : drawOne
42
39
} ;
43
40
41
+ /*
42
+ * draw: draw all annotations without any new modifications
43
+ */
44
44
function draw ( gd ) {
45
45
var fullLayout = gd . _fullLayout ;
46
46
@@ -55,196 +55,26 @@ function draw(gd) {
55
55
return Plots . previousPromises ( gd ) ;
56
56
}
57
57
58
- function drawOne ( gd , index , opt , value ) {
58
+ /*
59
+ * drawOne: draw a single annotation, potentially with modifications
60
+ *
61
+ * index (int): the annotation to draw
62
+ */
63
+ function drawOne ( gd , index ) {
59
64
var layout = gd . layout ,
60
65
fullLayout = gd . _fullLayout ,
61
- i ;
62
-
63
- if ( ! isNumeric ( index ) || index === - 1 ) {
64
-
65
- // no index provided - we're operating on ALL annotations
66
- if ( ! index && Array . isArray ( value ) ) {
67
- // a whole annotation array is passed in
68
- // (as in, redo of delete all)
69
- layout . annotations = value ;
70
- supplyLayoutDefaults ( layout , fullLayout ) ;
71
- draw ( gd ) ;
72
- return ;
73
- }
74
- else if ( value === 'remove' ) {
75
- // delete all
76
- delete layout . annotations ;
77
- fullLayout . annotations = [ ] ;
78
- draw ( gd ) ;
79
- return ;
80
- }
81
- else if ( opt && value !== 'add' ) {
82
- // make the same change to all annotations
83
- for ( i = 0 ; i < fullLayout . annotations . length ; i ++ ) {
84
- drawOne ( gd , i , opt , value ) ;
85
- }
86
- return ;
87
- }
88
- else {
89
- // add a new empty annotation
90
- index = fullLayout . annotations . length ;
91
- fullLayout . annotations . push ( { } ) ;
92
- }
93
- }
94
-
95
- if ( ! opt && value ) {
96
- if ( value === 'remove' ) {
97
- fullLayout . _infolayer . selectAll ( '.annotation[data-index="' + index + '"]' )
98
- . remove ( ) ;
99
- fullLayout . annotations . splice ( index , 1 ) ;
100
- layout . annotations . splice ( index , 1 ) ;
101
- for ( i = index ; i < fullLayout . annotations . length ; i ++ ) {
102
- fullLayout . _infolayer
103
- . selectAll ( '.annotation[data-index="' + ( i + 1 ) + '"]' )
104
- . attr ( 'data-index' , String ( i ) ) ;
105
-
106
- // redraw all annotations past the removed one,
107
- // so they bind to the right events
108
- drawOne ( gd , i ) ;
109
- }
110
- return ;
111
- }
112
- else if ( value === 'add' || Lib . isPlainObject ( value ) ) {
113
- fullLayout . annotations . splice ( index , 0 , { } ) ;
114
-
115
- var rule = Lib . isPlainObject ( value ) ?
116
- Lib . extendFlat ( { } , value ) :
117
- { text : 'New text' } ;
118
-
119
- if ( layout . annotations ) {
120
- layout . annotations . splice ( index , 0 , rule ) ;
121
- } else {
122
- layout . annotations = [ rule ] ;
123
- }
124
-
125
- for ( i = fullLayout . annotations . length - 1 ; i > index ; i -- ) {
126
- fullLayout . _infolayer
127
- . selectAll ( '.annotation[data-index="' + ( i - 1 ) + '"]' )
128
- . attr ( 'data-index' , String ( i ) ) ;
129
- drawOne ( gd , i ) ;
130
- }
131
- }
132
- }
66
+ gs = gd . _fullLayout . _size ;
133
67
134
68
// remove the existing annotation if there is one
135
69
fullLayout . _infolayer . selectAll ( '.annotation[data-index="' + index + '"]' ) . remove ( ) ;
136
70
137
71
// remember a few things about what was already there,
138
72
var optionsIn = layout . annotations [ index ] ,
139
- oldPrivate = fullLayout . annotations [ index ] ;
140
-
141
- // not sure how we're getting here... but C12 is seeing a bug
142
- // where we fail here when they add/remove annotations
143
- if ( ! optionsIn ) return ;
73
+ options = fullLayout . annotations [ index ] ;
144
74
145
- // alter the input annotation as requested
146
- var optionsEdit = { } ;
147
- if ( typeof opt === 'string' && opt ) optionsEdit [ opt ] = value ;
148
- else if ( Lib . isPlainObject ( opt ) ) optionsEdit = opt ;
149
-
150
- var optionKeys = Object . keys ( optionsEdit ) ;
151
- for ( i = 0 ; i < optionKeys . length ; i ++ ) {
152
- var k = optionKeys [ i ] ;
153
- Lib . nestedProperty ( optionsIn , k ) . set ( optionsEdit [ k ] ) ;
154
- }
155
-
156
- // return early in visible: false updates
157
- if ( optionsIn . visible === false ) return ;
158
-
159
- var gs = fullLayout . _size ;
160
- var oldRef = { xref : oldPrivate . xref , yref : oldPrivate . yref } ;
161
-
162
- var axLetters = [ 'x' , 'y' ] ;
163
- for ( i = 0 ; i < 2 ; i ++ ) {
164
- var axLetter = axLetters [ i ] ;
165
- // if we don't have an explicit position already,
166
- // don't set one just because we're changing references
167
- // or axis type.
168
- // the defaults will be consistent most of the time anyway,
169
- // except in log/linear changes
170
- if ( optionsEdit [ axLetter ] !== undefined ||
171
- optionsIn [ axLetter ] === undefined ) {
172
- continue ;
173
- }
174
-
175
- var axOld = Axes . getFromId ( gd , Axes . coerceRef ( oldRef , { } , gd , axLetter , '' , 'paper' ) ) ,
176
- axNew = Axes . getFromId ( gd , Axes . coerceRef ( optionsIn , { } , gd , axLetter , '' , 'paper' ) ) ,
177
- position = optionsIn [ axLetter ] ,
178
- axTypeOld = oldPrivate [ '_' + axLetter + 'type' ] ;
179
-
180
- if ( optionsEdit [ axLetter + 'ref' ] !== undefined ) {
181
-
182
- // TODO: include ax / ay / axref / ayref here if not 'pixel'
183
- // or even better, move all of this machinery out of here and into
184
- // streambed as extra attributes to a regular relayout call
185
- // we should do this after v2.0 when it can work equivalently for
186
- // annotations, shapes, and images.
187
-
188
- var autoAnchor = optionsIn [ axLetter + 'anchor' ] === 'auto' ,
189
- plotSize = ( axLetter === 'x' ? gs . w : gs . h ) ,
190
- halfSizeFrac = ( oldPrivate [ '_' + axLetter + 'size' ] || 0 ) /
191
- ( 2 * plotSize ) ;
192
- if ( axOld && axNew ) { // data -> different data
193
- // go to the same fraction of the axis length
194
- // whether or not these axes share a domain
195
-
196
- position = axNew . fraction2r ( axOld . r2fraction ( position ) ) ;
197
- }
198
- else if ( axOld ) { // data -> paper
199
- // first convert to fraction of the axis
200
- position = axOld . r2fraction ( position ) ;
201
-
202
- // next scale the axis to the whole plot
203
- position = axOld . domain [ 0 ] +
204
- position * ( axOld . domain [ 1 ] - axOld . domain [ 0 ] ) ;
205
-
206
- // finally see if we need to adjust auto alignment
207
- // because auto always means middle / center alignment for data,
208
- // but it changes for page alignment based on the closest side
209
- if ( autoAnchor ) {
210
- var posPlus = position + halfSizeFrac ,
211
- posMinus = position - halfSizeFrac ;
212
- if ( position + posMinus < 2 / 3 ) position = posMinus ;
213
- else if ( position + posPlus > 4 / 3 ) position = posPlus ;
214
- }
215
- }
216
- else if ( axNew ) { // paper -> data
217
- // first see if we need to adjust auto alignment
218
- if ( autoAnchor ) {
219
- if ( position < 1 / 3 ) position += halfSizeFrac ;
220
- else if ( position > 2 / 3 ) position -= halfSizeFrac ;
221
- }
222
-
223
- // next convert to fraction of the axis
224
- position = ( position - axNew . domain [ 0 ] ) /
225
- ( axNew . domain [ 1 ] - axNew . domain [ 0 ] ) ;
226
-
227
- // finally convert to data coordinates
228
- position = axNew . fraction2r ( position ) ;
229
- }
230
- }
231
-
232
- if ( axNew && axNew === axOld && axTypeOld ) {
233
- if ( axTypeOld === 'log' && axNew . type !== 'log' ) {
234
- position = Math . pow ( 10 , position ) ;
235
- }
236
- else if ( axTypeOld !== 'log' && axNew . type === 'log' ) {
237
- position = ( position > 0 ) ?
238
- Math . log ( position ) / Math . LN10 : undefined ;
239
- }
240
- }
241
-
242
- optionsIn [ axLetter ] = position ;
243
- }
244
-
245
- var options = { } ;
246
- handleAnnotationDefaults ( optionsIn , options , fullLayout ) ;
247
- fullLayout . annotations [ index ] = options ;
75
+ // this annotation is gone - quit now after deleting it
76
+ // TODO: use d3 idioms instead of deleting and redrawing every time
77
+ if ( ! optionsIn || options . visible === false ) return ;
248
78
249
79
var xa = Axes . getFromId ( gd , options . xref ) ,
250
80
ya = Axes . getFromId ( gd , options . yref ) ,
@@ -457,9 +287,6 @@ function drawOne(gd, index, opt, value) {
457
287
458
288
options [ '_' + axLetter + 'padplus' ] = ( annSize / 2 ) + textPadShift ;
459
289
options [ '_' + axLetter + 'padminus' ] = ( annSize / 2 ) - textPadShift ;
460
-
461
- // save the current axis type for later log/linear changes
462
- options [ '_' + axLetter + 'type' ] = ax && ax . type ;
463
290
} ) ;
464
291
465
292
if ( annotationIsOffscreen ) {
0 commit comments