25d7fa609458c0b6ef60355c7d6b1177a3d86f8e5e8901d34f71d26b2241961df51a344644ac4c373247890c10778c66ed4550d03004df082cbb601aebfa24 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. import { heightAtLine } from "../line/spans.js"
  2. import { getLine, lineAtHeight, updateLineHeight } from "../line/utils_line.js"
  3. import { paddingTop, charWidth } from "../measurement/position_measurement.js"
  4. import { ie, ie_version } from "../util/browser.js"
  5. // Read the actual heights of the rendered lines, and update their
  6. // stored heights to match.
  7. export function updateHeightsInViewport(cm) {
  8. let display = cm.display
  9. let prevBottom = display.lineDiv.offsetTop
  10. let viewTop = Math.max(0, display.scroller.getBoundingClientRect().top)
  11. let oldHeight = display.lineDiv.getBoundingClientRect().top
  12. let mustScroll = 0
  13. for (let i = 0; i < display.view.length; i++) {
  14. let cur = display.view[i], wrapping = cm.options.lineWrapping
  15. let height, width = 0
  16. if (cur.hidden) continue
  17. oldHeight += cur.line.height
  18. if (ie && ie_version < 8) {
  19. let bot = cur.node.offsetTop + cur.node.offsetHeight
  20. height = bot - prevBottom
  21. prevBottom = bot
  22. } else {
  23. let box = cur.node.getBoundingClientRect()
  24. height = box.bottom - box.top
  25. // Check that lines don't extend past the right of the current
  26. // editor width
  27. if (!wrapping && cur.text.firstChild)
  28. width = cur.text.firstChild.getBoundingClientRect().right - box.left - 1
  29. }
  30. let diff = cur.line.height - height
  31. if (diff > .005 || diff < -.005) {
  32. if (oldHeight < viewTop) mustScroll -= diff
  33. updateLineHeight(cur.line, height)
  34. updateWidgetHeight(cur.line)
  35. if (cur.rest) for (let j = 0; j < cur.rest.length; j++)
  36. updateWidgetHeight(cur.rest[j])
  37. }
  38. if (width > cm.display.sizerWidth) {
  39. let chWidth = Math.ceil(width / charWidth(cm.display))
  40. if (chWidth > cm.display.maxLineLength) {
  41. cm.display.maxLineLength = chWidth
  42. cm.display.maxLine = cur.line
  43. cm.display.maxLineChanged = true
  44. }
  45. }
  46. }
  47. if (Math.abs(mustScroll) > 2) display.scroller.scrollTop += mustScroll
  48. }
  49. // Read and store the height of line widgets associated with the
  50. // given line.
  51. function updateWidgetHeight(line) {
  52. if (line.widgets) for (let i = 0; i < line.widgets.length; ++i) {
  53. let w = line.widgets[i], parent = w.node.parentNode
  54. if (parent) w.height = parent.offsetHeight
  55. }
  56. }
  57. // Compute the lines that are visible in a given viewport (defaults
  58. // the current scroll position). viewport may contain top,
  59. // height, and ensure (see op.scrollToPos) properties.
  60. export function visibleLines(display, doc, viewport) {
  61. let top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop
  62. top = Math.floor(top - paddingTop(display))
  63. let bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight
  64. let from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom)
  65. // Ensure is a {from: {line, ch}, to: {line, ch}} object, and
  66. // forces those lines into the viewport (if possible).
  67. if (viewport && viewport.ensure) {
  68. let ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line
  69. if (ensureFrom < from) {
  70. from = ensureFrom
  71. to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight)
  72. } else if (Math.min(ensureTo, doc.lastLine()) >= to) {
  73. from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight)
  74. to = ensureTo
  75. }
  76. }
  77. return {from: from, to: Math.max(to, from + 1)}
  78. }