提交 639558ef 编写于 作者: A Alex Dima

Fixes #20935: Add dragging to the minimap slider

上级 e36134fa
......@@ -82,6 +82,10 @@ export abstract class FastDomNode<T extends HTMLElement> {
this._domNode.style.height = this._height + 'px';
}
public getHeight(): number {
return this._height;
}
public unsetHeight(): void {
if (this._height === -1) {
return;
......@@ -98,6 +102,10 @@ export abstract class FastDomNode<T extends HTMLElement> {
this._domNode.style.top = this._top + 'px';
}
public getTop(): number {
return this._top;
}
public unsetTop(): void {
if (this._top === -1) {
return;
......
......@@ -24,6 +24,8 @@ import { RenderedLinesCollection, ILine } from 'vs/editor/browser/view/viewLayer
import { Range } from 'vs/editor/common/core/range';
import { RGBA } from 'vs/base/common/color';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { GlobalMouseMoveMonitor, IStandardMouseMoveEventData, standardMouseMoveMerger } from 'vs/base/browser/globalMouseMoveMonitor';
import * as platform from 'vs/base/common/platform';
const enum RenderMinimap {
None = 0,
......@@ -61,6 +63,11 @@ function getMinimapCharWidth(renderMinimap: RenderMinimap): number {
return Constants.x1_CHAR_WIDTH;
}
/**
* The orthogonal distance to the slider at which dragging "resets". This implements "snapping"
*/
const MOUSE_DRAG_RESET_DISTANCE = 140;
class MinimapOptions {
public readonly renderMinimap: RenderMinimap;
......@@ -241,7 +248,17 @@ class MinimapLayout {
}
this.sliderTop = Math.floor((viewportStartLineNumber - this.startLineNumber) * minimapLineHeight / pixelRatio);
this.sliderHeight = Math.floor(viewportLineCount * minimapLineHeight / pixelRatio);
if (viewportEndLineNumber === lineCount) {
// The last line is in the viewport => try to extend slider height below the painted lines
let desiredSliderHeight = Math.floor(expectedViewportLineCount * minimapLineHeight / pixelRatio);
if (this.sliderTop + desiredSliderHeight > options.minimapHeight) {
this.sliderHeight = options.minimapHeight - this.sliderTop;
} else {
this.sliderHeight = desiredSliderHeight;
}
} else {
this.sliderHeight = Math.floor(viewportLineCount * minimapLineHeight / pixelRatio);
}
}
}
......@@ -404,6 +421,8 @@ export class Minimap extends ViewPart {
private readonly _slider: FastDomNode<HTMLElement>;
private readonly _tokensColorTracker: MinimapTokensColorTracker;
private readonly _mouseDownListener: IDisposable;
private readonly _sliderMouseMoveMonitor: GlobalMouseMoveMonitor<IStandardMouseMoveEventData>;
private readonly _sliderMouseDownListener: IDisposable;
private readonly _minimapCharRenderer: MinimapCharRenderer;
......@@ -468,10 +487,63 @@ export class Minimap extends ViewPart {
false
));
});
this._sliderMouseMoveMonitor = new GlobalMouseMoveMonitor<IStandardMouseMoveEventData>();
this._sliderMouseDownListener = dom.addStandardDisposableListener(this._slider.domNode, 'mousedown', (e) => {
e.preventDefault();
if (e.leftButton) {
const initialMouseOrthogonalPosition = e.posx;
const initialScrollTop = this._viewLayout.getScrollTop();
const initialSliderCenter = (this._slider.getTop() + this._slider.getHeight() / 2);
const draggingDeltaCenter = e.posy - initialSliderCenter;
this._slider.toggleClassName('active', true);
this._sliderMouseMoveMonitor.startMonitoring(
standardMouseMoveMerger,
(mouseMoveData: IStandardMouseMoveEventData) => {
const mouseOrthogonalPosition = mouseMoveData.posx;
const mouseOrthogonalDelta = Math.abs(mouseOrthogonalPosition - initialMouseOrthogonalPosition);
if (platform.isWindows && mouseOrthogonalDelta > MOUSE_DRAG_RESET_DISTANCE) {
// The mouse has wondered away from the slider => reset dragging
this._viewLayout.setScrollPosition({
scrollTop: initialScrollTop
});
} else {
const pixelRatio = this._options.pixelRatio;
const minimapLineHeight = getMinimapLineHeight(this._options.renderMinimap);
const entireCanvasOuterHeight = this._context.model.getLineCount() * minimapLineHeight / pixelRatio;
const representableHeight = Math.min(entireCanvasOuterHeight, this._options.canvasOuterHeight);
// Account for the fact that the minimap does not render the extra space below the viewport
let discountScrollHeight = 0;
if (this._context.configuration.editor.viewInfo.scrollBeyondLastLine) {
discountScrollHeight = this._canvas.getHeight() - this._context.configuration.editor.lineHeight;
}
const scrollHeight = this._viewLayout.getScrollHeight() - discountScrollHeight;
const desiredSliderCenter = mouseMoveData.posy - draggingDeltaCenter;
const desiredScrollCenter = desiredSliderCenter * (scrollHeight / representableHeight);
const desiredScrollTop = desiredScrollCenter - this._canvas.getHeight() / 2;
this._viewLayout.setScrollPosition({
scrollTop: desiredScrollTop
});
}
},
() => {
this._slider.toggleClassName('active', false);
}
);
}
});
}
public dispose(): void {
this._mouseDownListener.dispose();
this._sliderMouseMoveMonitor.dispose();
this._sliderMouseDownListener.dispose();
super.dispose();
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册