mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-09-20 15:37:46 +03:00
Add avoidOverflow: false option for overlays
This commit is contained in:
parent
f2e2475c62
commit
5297e7ab1a
@ -876,17 +876,22 @@ describe('TextEditorComponent', () => {
|
||||
})
|
||||
|
||||
describe('overlay decorations', () => {
|
||||
it('renders overlay elements at the specified screen position unless it would overflow the window', async () => {
|
||||
const {component, element, editor} = buildComponent({width: 200, height: 100, attach: false})
|
||||
function attachFakeWindow (component) {
|
||||
const fakeWindow = document.createElement('div')
|
||||
fakeWindow.style.position = 'absolute'
|
||||
fakeWindow.style.padding = 20 + 'px'
|
||||
fakeWindow.style.backgroundColor = 'blue'
|
||||
fakeWindow.appendChild(element)
|
||||
fakeWindow.appendChild(component.element)
|
||||
jasmine.attachToDOM(fakeWindow)
|
||||
|
||||
spyOn(component, 'getWindowInnerWidth').andCallFake(() => fakeWindow.getBoundingClientRect().width)
|
||||
spyOn(component, 'getWindowInnerHeight').andCallFake(() => fakeWindow.getBoundingClientRect().height)
|
||||
return fakeWindow
|
||||
}
|
||||
|
||||
it('renders overlay elements at the specified screen position unless it would overflow the window', async () => {
|
||||
const {component, element, editor} = buildComponent({width: 200, height: 100, attach: false})
|
||||
const fakeWindow = attachFakeWindow(component)
|
||||
|
||||
await setScrollTop(component, 50)
|
||||
await setScrollLeft(component, 100)
|
||||
|
||||
@ -949,6 +954,24 @@ describe('TextEditorComponent', () => {
|
||||
await component.getNextUpdatePromise()
|
||||
expect(overlayWrapper.classList.contains('b')).toBe(false)
|
||||
})
|
||||
|
||||
it('does not attempt to avoid overflowing the window if `avoidOverflow` is false on the decoration', async () => {
|
||||
const {component, element, editor} = buildComponent({width: 200, height: 100, attach: false})
|
||||
const fakeWindow = attachFakeWindow(component)
|
||||
const overlayElement = document.createElement('div')
|
||||
overlayElement.style.width = '50px'
|
||||
overlayElement.style.height = '50px'
|
||||
overlayElement.style.margin = '3px'
|
||||
overlayElement.style.backgroundColor = 'red'
|
||||
const marker = editor.markScreenPosition([4, 25])
|
||||
const decoration = editor.decorateMarker(marker, {type: 'overlay', item: overlayElement, avoidOverflow: false})
|
||||
await component.getNextUpdatePromise()
|
||||
|
||||
await setScrollLeft(component, 30)
|
||||
expect(overlayElement.getBoundingClientRect().right).toBeGreaterThan(fakeWindow.getBoundingClientRect().right)
|
||||
await setScrollLeft(component, 280)
|
||||
expect(overlayElement.getBoundingClientRect().left).toBeLessThan(fakeWindow.getBoundingClientRect().left)
|
||||
})
|
||||
})
|
||||
|
||||
describe('mouse input', () => {
|
||||
|
@ -576,7 +576,10 @@ class TextEditorComponent {
|
||||
|
||||
renderOverlayDecorations () {
|
||||
return this.decorationsToRender.overlays.map((overlayProps) =>
|
||||
$(OverlayComponent, Object.assign({didResize: this.updateSync}, overlayProps))
|
||||
$(OverlayComponent, Object.assign(
|
||||
{key: overlayProps.element, didResize: this.updateSync},
|
||||
overlayProps
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
@ -728,17 +731,14 @@ class TextEditorComponent {
|
||||
}
|
||||
|
||||
addOverlayDecorationToRender (decoration, marker) {
|
||||
const {class: className, item, position} = decoration
|
||||
const {class: className, item, position, avoidOverflow} = decoration
|
||||
const element = atom.views.getView(item)
|
||||
const screenPosition = (position === 'tail')
|
||||
? marker.getTailScreenPosition()
|
||||
: marker.getHeadScreenPosition()
|
||||
|
||||
this.requestHorizontalMeasurement(screenPosition.row, screenPosition.column)
|
||||
this.decorationsToRender.overlays.push({
|
||||
key: element,
|
||||
className, element, screenPosition
|
||||
})
|
||||
this.decorationsToRender.overlays.push({className, element, avoidOverflow, screenPosition})
|
||||
}
|
||||
|
||||
updateAbsolutePositionedDecorations () {
|
||||
@ -792,27 +792,28 @@ class TextEditorComponent {
|
||||
const contentClientRect = this.refs.content.getBoundingClientRect()
|
||||
for (let i = 0; i < overlayCount; i++) {
|
||||
const decoration = this.decorationsToRender.overlays[i]
|
||||
const {element, screenPosition} = decoration
|
||||
const {element, screenPosition, avoidOverflow} = decoration
|
||||
const {row, column} = screenPosition
|
||||
const computedStyle = window.getComputedStyle(element)
|
||||
|
||||
let wrapperTop = contentClientRect.top + this.pixelTopForRow(row) + this.getLineHeight()
|
||||
const elementHeight = element.offsetHeight
|
||||
const elementTop = wrapperTop + parseInt(computedStyle.marginTop)
|
||||
const elementBottom = elementTop + elementHeight
|
||||
const flippedElementTop = wrapperTop - this.getLineHeight() - elementHeight - parseInt(computedStyle.marginBottom)
|
||||
|
||||
if (elementBottom > windowInnerHeight && flippedElementTop >= 0) {
|
||||
wrapperTop -= (elementTop - flippedElementTop)
|
||||
}
|
||||
|
||||
let wrapperLeft = contentClientRect.left + this.pixelLeftForRowAndColumn(row, column)
|
||||
const elementLeft = wrapperLeft + parseInt(computedStyle.marginLeft)
|
||||
const elementRight = elementLeft + element.offsetWidth
|
||||
if (elementLeft < 0) {
|
||||
wrapperLeft -= elementLeft
|
||||
} else if (elementRight > windowInnerWidth) {
|
||||
wrapperLeft -= (elementRight - windowInnerWidth)
|
||||
|
||||
if (avoidOverflow !== false) {
|
||||
const computedStyle = window.getComputedStyle(element)
|
||||
const elementHeight = element.offsetHeight
|
||||
const elementTop = wrapperTop + parseInt(computedStyle.marginTop)
|
||||
const elementBottom = elementTop + elementHeight
|
||||
const flippedElementTop = wrapperTop - this.getLineHeight() - elementHeight - parseInt(computedStyle.marginBottom)
|
||||
const elementLeft = wrapperLeft + parseInt(computedStyle.marginLeft)
|
||||
const elementRight = elementLeft + element.offsetWidth
|
||||
|
||||
if (elementBottom > windowInnerHeight && flippedElementTop >= 0) {
|
||||
wrapperTop -= (elementTop - flippedElementTop)
|
||||
}
|
||||
if (elementLeft < 0) {
|
||||
wrapperLeft -= elementLeft
|
||||
} else if (elementRight > windowInnerWidth) {
|
||||
wrapperLeft -= (elementRight - windowInnerWidth)
|
||||
}
|
||||
}
|
||||
|
||||
decoration.pixelTop = wrapperTop
|
||||
|
Loading…
Reference in New Issue
Block a user