@@ -1407,27 +1407,79 @@ testCM("lineWidgetCautiousRedraw", function(cm) {
14071407 is ( ! redrawn ) ;
14081408} , { value : "123\n456" } ) ;
14091409
1410+
1411+ var knownScrollbarWidth ;
1412+ function scrollbarWidth ( measure ) {
1413+ if ( knownScrollbarWidth != null ) return knownScrollbarWidth ;
1414+ var div = document . createElement ( 'div' ) ;
1415+ div . style . cssText = "width: 50px; height: 50px; overflow-x: scroll" ;
1416+ document . body . appendChild ( div ) ;
1417+ knownScrollbarWidth = div . offsetHeight - div . clientHeight ;
1418+ document . body . removeChild ( div ) ;
1419+ return knownScrollbarWidth || 0 ;
1420+ }
1421+
14101422testCM ( "lineWidgetChanged" , function ( cm ) {
14111423 addDoc ( cm , 2 , 300 ) ;
1412- cm . setSize ( null , cm . defaultTextHeight ( ) * 50 ) ;
1424+ var halfScrollbarWidth = scrollbarWidth ( cm . display . measure ) / 2 ;
1425+ cm . setOption ( 'lineNumbers' , true ) ;
1426+ cm . setSize ( 600 , cm . defaultTextHeight ( ) * 50 ) ;
14131427 cm . scrollTo ( null , cm . heightAtLine ( 125 , "local" ) ) ;
1428+
1429+ var expectedWidgetHeight = 60 ;
1430+ var expectedLinesInWidget = 3 ;
14141431 function w ( ) {
14151432 var node = document . createElement ( "div" ) ;
1416- node . style . cssText = "background: yellow; height: 50px;" ;
1433+ // we use these children with just under half width of the line to check measurements are made with correct width
1434+ // when placed in the measure div.
1435+ // If the widget is measured at a width much narrower than it is displayed at, the underHalf children will span two lines and break the test.
1436+ // If the widget is measured at a width much wider than it is displayed at, the overHalf children will combine and break the test.
1437+ // Note that this test only checks widgets where coverGutter is true, because these require extra styling to get the width right.
1438+ // It may also be worthwhile to check this for non-coverGutter widgets.
1439+ // Visually:
1440+ // Good:
1441+ // | ------------- display width ------------- |
1442+ // | ------- widget-width when measured ------ |
1443+ // | | -- under-half -- | | -- under-half -- | |
1444+ // | | --- over-half --- | |
1445+ // | | --- over-half --- | |
1446+ // Height: measured as 3 lines, same as it will be when actually displayed
1447+
1448+ // Bad (too narrow):
1449+ // | ------------- display width ------------- |
1450+ // | ------ widget-width when measured ----- | < -- uh oh
1451+ // | | -- under-half -- | |
1452+ // | | -- under-half -- | | < -- when measured, shoved to next line
1453+ // | | --- over-half --- | |
1454+ // | | --- over-half --- | |
1455+ // Height: measured as 4 lines, more than expected . Will be displayed as 3 lines!
1456+
1457+ // Bad (too wide):
1458+ // | ------------- display width ------------- |
1459+ // | -------- widget-width when measured ------- | < -- uh oh
1460+ // | | -- under-half -- | | -- under-half -- | |
1461+ // | | --- over-half --- | | --- over-half --- | | < -- when measured, combined on one line
1462+ // Height: measured as 2 lines, less than expected. Will be displayed as 3 lines!
1463+
1464+ var barelyUnderHalfWidthHtml = '<div style="display: inline-block; height: 1px; width: ' + ( 285 - halfScrollbarWidth ) + 'px;"></div>' ;
1465+ var barelyOverHalfWidthHtml = '<div style="display: inline-block; height: 1px; width: ' + ( 305 - halfScrollbarWidth ) + 'px;"></div>' ;
1466+ node . innerHTML = new Array ( 3 ) . join ( barelyUnderHalfWidthHtml ) + new Array ( 3 ) . join ( barelyOverHalfWidthHtml ) ;
1467+ node . style . cssText = "background: yellow;font-size:0;line-height: " + ( expectedWidgetHeight / expectedLinesInWidget ) + "px;" ;
14171468 return node ;
14181469 }
14191470 var info0 = cm . getScrollInfo ( ) ;
1420- var w0 = cm . addLineWidget ( 0 , w ( ) ) ;
1421- var w150 = cm . addLineWidget ( 150 , w ( ) ) ;
1422- var w300 = cm . addLineWidget ( 300 , w ( ) ) ;
1471+ var w0 = cm . addLineWidget ( 0 , w ( ) , { coverGutter : true } ) ;
1472+ var w150 = cm . addLineWidget ( 150 , w ( ) , { coverGutter : true } ) ;
1473+ var w300 = cm . addLineWidget ( 300 , w ( ) , { coverGutter : true } ) ;
14231474 var info1 = cm . getScrollInfo ( ) ;
1424- eq ( info0 . height + 150 , info1 . height ) ;
1425- eq ( info0 . top + 50 , info1 . top ) ;
1426- w0 . node . style . height = w150 . node . style . height = w300 . node . style . height = "10px" ;
1475+ eq ( info0 . height + ( 3 * expectedWidgetHeight ) , info1 . height ) ;
1476+ eq ( info0 . top + expectedWidgetHeight , info1 . top ) ;
1477+ expectedWidgetHeight = 12 ;
1478+ w0 . node . style . lineHeight = w150 . node . style . lineHeight = w300 . node . style . lineHeight = ( expectedWidgetHeight / expectedLinesInWidget ) + "px" ;
14271479 w0 . changed ( ) ; w150 . changed ( ) ; w300 . changed ( ) ;
14281480 var info2 = cm . getScrollInfo ( ) ;
1429- eq ( info0 . height + 30 , info2 . height ) ;
1430- eq ( info0 . top + 10 , info2 . top ) ;
1481+ eq ( info0 . height + ( 3 * expectedWidgetHeight ) , info2 . height ) ;
1482+ eq ( info0 . top + expectedWidgetHeight , info2 . top ) ;
14311483} ) ;
14321484
14331485testCM ( "getLineNumber" , function ( cm ) {
0 commit comments