mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-27 01:25:36 -05:00
Markdown Horizontal Scrollbar Fix (#17083)
* dynamically change horizontal scrollbar * working horizontal scrollbar * created new event to handle both scrollbar and mouse wheel * only show scrollbar when needed
This commit is contained in:
@@ -37,6 +37,7 @@ export class QueryTextEditor extends BaseTextEditor {
|
||||
private _hideLineNumbers: boolean;
|
||||
private _scrollbarHeight: number;
|
||||
private _lineHeight: number;
|
||||
private _shouldAddHorizontalScrollbarHeight: boolean = false;
|
||||
|
||||
constructor(
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@@ -123,6 +124,10 @@ export class QueryTextEditor extends BaseTextEditor {
|
||||
return editorWidget.getScrollHeight();
|
||||
}
|
||||
|
||||
public get shouldAddHorizontalScrollbar(): boolean {
|
||||
return this._shouldAddHorizontalScrollbarHeight;
|
||||
}
|
||||
|
||||
public setHeightToScrollHeight(configChanged?: boolean, isEditorCollapsed?: boolean,) {
|
||||
let editorWidget = this.getControl() as ICodeEditor;
|
||||
let layoutInfo = editorWidget.getLayoutInfo();
|
||||
@@ -146,7 +151,7 @@ export class QueryTextEditor extends BaseTextEditor {
|
||||
// number of lines that wrap). Finally, viewportColumn is calculated on editor resizing automatically; we can use it to ensure
|
||||
// that the viewportColumn will always be greater than any character's column in an editor.
|
||||
let numberWrappedLines = 0;
|
||||
let shouldAddHorizontalScrollbarHeight = false;
|
||||
this._shouldAddHorizontalScrollbarHeight = false;
|
||||
if (!this._lineHeight || configChanged) {
|
||||
this._lineHeight = editorWidget.getOption(EditorOption.lineHeight) || 18;
|
||||
}
|
||||
@@ -162,14 +167,14 @@ export class QueryTextEditor extends BaseTextEditor {
|
||||
for (let line = 1; line <= lineCount; line++) {
|
||||
// The horizontal scrollbar always appears 1 column past the viewport column when word wrap is disabled
|
||||
if (editorWidgetModel.getLineMaxColumn(line) >= layoutInfo.viewportColumn + 1) {
|
||||
shouldAddHorizontalScrollbarHeight = true;
|
||||
this._shouldAddHorizontalScrollbarHeight = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
let editorHeightUsingLines = this._lineHeight * (lineCount + numberWrappedLines);
|
||||
let editorHeightUsingMinHeight = Math.max(Math.min(editorHeightUsingLines, this._maxHeight), this._minHeight);
|
||||
editorHeightUsingMinHeight = shouldAddHorizontalScrollbarHeight ? editorHeightUsingMinHeight + this._scrollbarHeight : editorHeightUsingMinHeight;
|
||||
editorHeightUsingMinHeight = this._shouldAddHorizontalScrollbarHeight ? editorHeightUsingMinHeight + this._scrollbarHeight : editorHeightUsingMinHeight;
|
||||
this.setHeight(editorHeightUsingMinHeight);
|
||||
}
|
||||
|
||||
|
||||
@@ -242,6 +242,8 @@ export class CodeComponent extends CellView implements OnInit, OnChanges {
|
||||
|
||||
this.onContentChanged.emit();
|
||||
this.checkForLanguageMagics();
|
||||
// When content is updated we have to also update the horizontal scrollbar
|
||||
this.horizontalScrollbar();
|
||||
}));
|
||||
this._register(this._configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration('editor.wordWrap') || e.affectsConfiguration('editor.fontSize')) {
|
||||
@@ -249,6 +251,9 @@ export class CodeComponent extends CellView implements OnInit, OnChanges {
|
||||
}
|
||||
}));
|
||||
this._register(this.model.layoutChanged(() => this._layoutEmitter.fire(), this));
|
||||
// Handles mouse wheel and scrollbar events
|
||||
this._register(Event.debounce(this.model.onScroll.event, (l, e) => e, 250, /*leading=*/false)
|
||||
(() => this.horizontalScrollbar()));
|
||||
this._register(this.cellModel.onExecutionStateChange(event => {
|
||||
if (event === CellExecutionState.Running && !this.cellModel.stdInVisible) {
|
||||
this.setFocusAndScroll();
|
||||
@@ -264,7 +269,6 @@ export class CodeComponent extends CellView implements OnInit, OnChanges {
|
||||
}
|
||||
this._layoutEmitter.fire();
|
||||
}));
|
||||
|
||||
this.layout();
|
||||
|
||||
if (this._cellModel.isCollapsed) {
|
||||
@@ -277,6 +281,51 @@ export class CodeComponent extends CellView implements OnInit, OnChanges {
|
||||
DOM.getContentWidth(this.codeElement.nativeElement),
|
||||
DOM.getContentHeight(this.codeElement.nativeElement)));
|
||||
this._editor.setHeightToScrollHeight(false, this._cellModel.isCollapsed);
|
||||
this.horizontalScrollbar();
|
||||
}
|
||||
|
||||
/**
|
||||
* Horizontal Scrollbar function will ensure we only calculate and trigger this if word wrap is off and it is a markdown cell
|
||||
* This will adjust the horizontal scrollbar to either a fixed position at the bottom of the viewport (visible area)
|
||||
* or it will set it to the bottom of the markdown editor if it is in the viewport (visible area)
|
||||
*/
|
||||
public horizontalScrollbar(): void {
|
||||
let showScrollbar: boolean = this._editor.shouldAddHorizontalScrollbar;
|
||||
let horizontalScrollbar: HTMLElement = this.codeElement.nativeElement.querySelector('div.scrollbar.horizontal');
|
||||
if (this._configurationService.getValue('editor.wordWrap') === 'off' && this.cellModel.cellType !== CellTypes.Code && this.cellModel.source.length > 0 && showScrollbar) {
|
||||
// Get markdown split view horizontal scrollbar
|
||||
let viewport: HTMLElement = document.querySelector('.scrollable');
|
||||
let markdownEditor: HTMLElement = this.codeElement.nativeElement.closest('.show-markdown .editor');
|
||||
|
||||
//Get values based on current context of the editor and ADS window
|
||||
let markdownEditorBottom = Math.floor(markdownEditor.getBoundingClientRect().bottom);
|
||||
let viewportBottom = Math.floor(viewport.getBoundingClientRect().bottom);
|
||||
let viewportHeight = DOM.getTotalHeight(viewport);
|
||||
let viewportTop = Math.floor(document.querySelector('.scrollable').getBoundingClientRect().top);
|
||||
|
||||
// Have to offset the height based on the contents viewport and the additional scrollbars that are present in markdown editor and notebook
|
||||
let horizontalTop = Math.floor(Math.abs(viewportTop + viewportHeight) - Math.abs(2 * horizontalScrollbar.scrollHeight));
|
||||
|
||||
// Set opacity for both fixed and absolute
|
||||
horizontalScrollbar.style.opacity = '1';
|
||||
|
||||
// If the bottom of the editor is in the viewport, then set the horizontal scrollbar to the bottom of the editor space
|
||||
if (markdownEditorBottom < viewportBottom) {
|
||||
horizontalScrollbar.style.position = 'absolute';
|
||||
horizontalScrollbar.style.left = '0px';
|
||||
horizontalScrollbar.style.top = '';
|
||||
horizontalScrollbar.style.bottom = '0px';
|
||||
// If the bottom of the editor is not in the viewport, then set the horizontal scrollbar to the bottom of the viewport
|
||||
} else {
|
||||
horizontalScrollbar.style.position = 'fixed';
|
||||
horizontalScrollbar.style.left = '';
|
||||
horizontalScrollbar.style.top = horizontalTop + 'px';
|
||||
horizontalScrollbar.style.bottom = '';
|
||||
}
|
||||
} else {
|
||||
// If horizontal scrollbar is not needed then set do not show it
|
||||
horizontalScrollbar.style.opacity = '0';
|
||||
}
|
||||
}
|
||||
|
||||
protected initActionBar() {
|
||||
|
||||
@@ -54,6 +54,7 @@ import { CellToolbarComponent } from 'sql/workbench/contrib/notebook/browser/cel
|
||||
import { NotebookViewsExtension } from 'sql/workbench/services/notebook/browser/notebookViews/notebookViewsExtension';
|
||||
import { MaskedLabeledMenuItemActionItem } from 'sql/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
|
||||
export const NOTEBOOK_SELECTOR: string = 'notebook-component';
|
||||
|
||||
@@ -84,6 +85,7 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
|
||||
private navigationResult: nb.NavigationResult;
|
||||
public previewFeaturesEnabled: boolean = false;
|
||||
public doubleClickEditEnabled: boolean;
|
||||
private _onScroll = new Emitter<void>();
|
||||
|
||||
constructor(
|
||||
@Inject(forwardRef(() => ChangeDetectorRef)) private _changeRef: ChangeDetectorRef,
|
||||
@@ -223,6 +225,7 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
|
||||
//Saves scrollTop value on scroll change
|
||||
public scrollHandler(event: Event) {
|
||||
this._scrollTop = (<HTMLElement>event.srcElement).scrollTop;
|
||||
this.model.onScroll.fire();
|
||||
}
|
||||
|
||||
public unselectActiveCell() {
|
||||
@@ -339,6 +342,7 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
|
||||
this._register(this._model.kernelChanged((kernelArgs) => this.handleKernelChanged(kernelArgs)));
|
||||
this._register(this._model.onCellTypeChanged(() => this.detectChanges()));
|
||||
this._register(this._model.layoutChanged(() => this.detectChanges()));
|
||||
this._register(this.model.onScroll.event(() => this._onScroll.fire()));
|
||||
|
||||
this.setLoading(false);
|
||||
// Check if URI fragment is present; if it is, navigate to section by default
|
||||
|
||||
@@ -80,6 +80,7 @@ export class NotebookModel extends Disposable implements INotebookModel {
|
||||
private _trustedMode: boolean;
|
||||
private _onActiveCellChanged = new Emitter<ICellModel | undefined>();
|
||||
private _onCellTypeChanged = new Emitter<ICellModel>();
|
||||
private _onScrollEmitter = new Emitter<void>();
|
||||
|
||||
private _cells: ICellModel[] | undefined;
|
||||
private _defaultLanguageInfo: nb.ILanguageInfo | undefined;
|
||||
@@ -213,6 +214,10 @@ export class NotebookModel extends Disposable implements INotebookModel {
|
||||
return this._contextsChangedEmitter.event;
|
||||
}
|
||||
|
||||
public get onScroll(): Emitter<void> {
|
||||
return this._onScrollEmitter;
|
||||
}
|
||||
|
||||
public get contextsLoading(): Event<void> {
|
||||
return this._contextsLoadingEmitter.event;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user