@@ -5,6 +5,7 @@ var Registry = require('../registry');
5
5
var Plots = require ( '../plots/plots' ) ;
6
6
7
7
var Lib = require ( '../lib' ) ;
8
+ var svgTextUtils = require ( '../lib/svg_text_utils' ) ;
8
9
var clearGlCanvases = require ( '../lib/clear_gl_canvases' ) ;
9
10
10
11
var Color = require ( '../components/color' ) ;
@@ -397,24 +398,120 @@ function findCounterAxisLineWidth(ax, side, counterAx, axList) {
397
398
}
398
399
399
400
exports . drawMainTitle = function ( gd ) {
401
+ var title = gd . _fullLayout . title ;
400
402
var fullLayout = gd . _fullLayout ;
401
-
402
403
var textAnchor = getMainTitleTextAnchor ( fullLayout ) ;
403
404
var dy = getMainTitleDy ( fullLayout ) ;
405
+ var y = getMainTitleY ( fullLayout , dy ) ;
406
+ var x = getMainTitleX ( fullLayout , textAnchor ) ;
404
407
405
408
Titles . draw ( gd , 'gtitle' , {
406
409
propContainer : fullLayout ,
407
410
propName : 'title.text' ,
408
411
placeholder : fullLayout . _dfltTitle . plot ,
409
- attributes : {
410
- x : getMainTitleX ( fullLayout , textAnchor ) ,
411
- y : getMainTitleY ( fullLayout , dy ) ,
412
+ attributes : ( {
413
+ x : x ,
414
+ y : y ,
412
415
'text-anchor' : textAnchor ,
413
416
dy : dy
414
- }
417
+ } )
415
418
} ) ;
419
+
420
+ if ( title . text && title . automargin ) {
421
+ var titleObj = d3 . selectAll ( '.gtitle' ) ;
422
+ var titleHeight = Drawing . bBox ( titleObj . node ( ) ) . height ;
423
+ var pushMargin = needsMarginPush ( gd , title , titleHeight ) ;
424
+ if ( pushMargin > 0 ) {
425
+ applyTitleAutoMargin ( gd , y , pushMargin , titleHeight ) ;
426
+ // Re-position the title once we know where it needs to be
427
+ titleObj . attr ( {
428
+ x : x ,
429
+ y : y ,
430
+ 'text-anchor' : textAnchor ,
431
+ dy : getMainTitleDyAdj ( title . yanchor )
432
+ } ) . call ( svgTextUtils . positionText , x , y ) ;
433
+ }
434
+ }
416
435
} ;
417
436
437
+
438
+ function isOutsideContainer ( gd , title , position , y , titleHeight ) {
439
+ var plotHeight = title . yref === 'paper' ? gd . _fullLayout . _size . h : gd . _fullLayout . height ;
440
+ var yPosTop = Lib . isTopAnchor ( title ) ? y : y - titleHeight ; // Standardize to the top of the title
441
+ var yPosRel = position === 'b' ? plotHeight - yPosTop : yPosTop ; // Position relative to the top or bottom of plot
442
+ if ( ( Lib . isTopAnchor ( title ) && position === 't' ) || Lib . isBottomAnchor ( title ) && position === 'b' ) {
443
+ return false ;
444
+ } else {
445
+ return yPosRel < titleHeight ;
446
+ }
447
+ }
448
+
449
+ function containerPushVal ( position , titleY , titleYanchor , height , titleDepth ) {
450
+ var push = 0 ;
451
+ if ( titleYanchor === 'middle' ) {
452
+ push += titleDepth / 2 ;
453
+ }
454
+ if ( position === 't' ) {
455
+ if ( titleYanchor === 'top' ) {
456
+ push += titleDepth ;
457
+ }
458
+ push += ( height - titleY * height ) ;
459
+ } else {
460
+ if ( titleYanchor === 'bottom' ) {
461
+ push += titleDepth ;
462
+ }
463
+ push += titleY * height ;
464
+ }
465
+ return push ;
466
+ }
467
+
468
+ function needsMarginPush ( gd , title , titleHeight ) {
469
+ var titleY = title . y ;
470
+ var titleYanchor = title . yanchor ;
471
+ var position = titleY > 0.5 ? 't' : 'b' ;
472
+ var curMargin = gd . _fullLayout . margin [ position ] ;
473
+ var pushMargin = 0 ;
474
+ if ( title . yref === 'paper' ) {
475
+ pushMargin = (
476
+ titleHeight +
477
+ title . pad . t +
478
+ title . pad . b
479
+ ) ;
480
+ } else if ( title . yref === 'container' ) {
481
+ pushMargin = (
482
+ containerPushVal ( position , titleY , titleYanchor , gd . _fullLayout . height , titleHeight ) +
483
+ title . pad . t +
484
+ title . pad . b
485
+ ) ;
486
+ }
487
+ if ( pushMargin > curMargin ) {
488
+ return pushMargin ;
489
+ }
490
+ return 0 ;
491
+ }
492
+
493
+ function applyTitleAutoMargin ( gd , y , pushMargin , titleHeight ) {
494
+ var titleID = 'title.automargin' ;
495
+ var title = gd . _fullLayout . title ;
496
+ var position = title . y > 0.5 ? 't' : 'b' ;
497
+ var push = {
498
+ x : title . x ,
499
+ y : title . y ,
500
+ t : 0 ,
501
+ b : 0
502
+ } ;
503
+ var reservedPush = { } ;
504
+
505
+ if ( title . yref === 'paper' && isOutsideContainer ( gd , title , position , y , titleHeight ) ) {
506
+ push [ position ] = pushMargin ;
507
+ } else if ( title . yref === 'container' ) {
508
+ reservedPush [ position ] = pushMargin ;
509
+ gd . _fullLayout . _reservedMargin [ titleID ] = reservedPush ;
510
+ }
511
+ Plots . allowAutoMargin ( gd , titleID ) ;
512
+ Plots . autoMargin ( gd , titleID , push ) ;
513
+ }
514
+
418
515
function getMainTitleX ( fullLayout , textAnchor ) {
419
516
var title = fullLayout . title ;
420
517
var gs = fullLayout . _size ;
@@ -439,7 +536,6 @@ function getMainTitleY(fullLayout, dy) {
439
536
var title = fullLayout . title ;
440
537
var gs = fullLayout . _size ;
441
538
var vPadShift = 0 ;
442
-
443
539
if ( dy === '0em' || ! dy ) {
444
540
vPadShift = - title . pad . b ;
445
541
} else if ( dy === alignmentConstants . CAP_SHIFT + 'em' ) {
@@ -459,6 +555,16 @@ function getMainTitleY(fullLayout, dy) {
459
555
}
460
556
}
461
557
558
+ function getMainTitleDyAdj ( yanchor ) {
559
+ if ( yanchor === 'top' ) {
560
+ return alignmentConstants . CAP_SHIFT + 0.3 + 'em' ;
561
+ } else if ( yanchor === 'bottom' ) {
562
+ return '-0.3em' ;
563
+ } else {
564
+ return alignmentConstants . MID_SHIFT + 'em' ;
565
+ }
566
+ }
567
+
462
568
function getMainTitleTextAnchor ( fullLayout ) {
463
569
var title = fullLayout . title ;
464
570
0 commit comments