mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-08 17:24:01 -05:00
Merge from vscode a5cf1da01d5db3d2557132be8d30f89c38019f6c (#8525)
* Merge from vscode a5cf1da01d5db3d2557132be8d30f89c38019f6c * remove files we don't want * fix hygiene * update distro * update distro * fix hygiene * fix strict nulls * distro * distro * fix tests * fix tests * add another edit * fix viewlet icon * fix azure dialog * fix some padding * fix more padding issues
This commit is contained in:
@@ -7,7 +7,7 @@ import 'vs/css!./media/tree';
|
||||
import { IDisposable, dispose, Disposable, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IListOptions, List, IListStyles, MouseController, DefaultKeyboardNavigationDelegate } from 'vs/base/browser/ui/list/listWidget';
|
||||
import { IListVirtualDelegate, IListRenderer, IListMouseEvent, IListEvent, IListContextMenuEvent, IListDragAndDrop, IListDragOverReaction, IKeyboardNavigationLabelProvider, IIdentityProvider, IKeyboardNavigationDelegate } from 'vs/base/browser/ui/list/list';
|
||||
import { append, $, toggleClass, getDomNodePagePosition, removeClass, addClass, hasClass, hasParentWithClass, createStyleSheet, clearNode } from 'vs/base/browser/dom';
|
||||
import { append, $, toggleClass, getDomNodePagePosition, removeClass, addClass, hasClass, hasParentWithClass, createStyleSheet, clearNode, addClasses, removeClasses } from 'vs/base/browser/dom';
|
||||
import { Event, Relay, Emitter, EventBufferer } from 'vs/base/common/event';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
@@ -27,10 +27,24 @@ import { clamp } from 'vs/base/common/numbers';
|
||||
import { ScrollEvent } from 'vs/base/common/scrollable';
|
||||
import { SetMap } from 'vs/base/common/collections';
|
||||
|
||||
class TreeElementsDragAndDropData<T, TFilterData, TContext> extends ElementsDragAndDropData<T, TContext> {
|
||||
|
||||
set context(context: TContext | undefined) {
|
||||
this.data.context = context;
|
||||
}
|
||||
|
||||
get context(): TContext | undefined {
|
||||
return this.data.context;
|
||||
}
|
||||
|
||||
constructor(private data: ElementsDragAndDropData<ITreeNode<T, TFilterData>, TContext>) {
|
||||
super(data.elements.map(node => node.element));
|
||||
}
|
||||
}
|
||||
|
||||
function asTreeDragAndDropData<T, TFilterData>(data: IDragAndDropData): IDragAndDropData {
|
||||
if (data instanceof ElementsDragAndDropData) {
|
||||
const nodes = (data as ElementsDragAndDropData<ITreeNode<T, TFilterData>>).elements;
|
||||
return new ElementsDragAndDropData(nodes.map(node => node.element));
|
||||
return new TreeElementsDragAndDropData(data);
|
||||
}
|
||||
|
||||
return data;
|
||||
@@ -47,9 +61,9 @@ class TreeNodeListDragAndDrop<T, TFilterData, TRef> implements IListDragAndDrop<
|
||||
return this.dnd.getDragURI(node.element);
|
||||
}
|
||||
|
||||
getDragLabel(nodes: ITreeNode<T, TFilterData>[]): string | undefined {
|
||||
getDragLabel(nodes: ITreeNode<T, TFilterData>[], originalEvent: DragEvent): string | undefined {
|
||||
if (this.dnd.getDragLabel) {
|
||||
return this.dnd.getDragLabel(nodes.map(node => node.element));
|
||||
return this.dnd.getDragLabel(nodes.map(node => node.element), originalEvent);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
@@ -87,7 +101,7 @@ class TreeNodeListDragAndDrop<T, TFilterData, TRef> implements IListDragAndDrop<
|
||||
}, 500);
|
||||
}
|
||||
|
||||
if (typeof result === 'boolean' || !result.accept || typeof result.bubble === 'undefined') {
|
||||
if (typeof result === 'boolean' || !result.accept || typeof result.bubble === 'undefined' || result.feedback) {
|
||||
if (!raw) {
|
||||
const accept = typeof result === 'boolean' ? result : result.accept;
|
||||
const effect = typeof result === 'boolean' ? undefined : result.effect;
|
||||
@@ -121,6 +135,12 @@ class TreeNodeListDragAndDrop<T, TFilterData, TRef> implements IListDragAndDrop<
|
||||
|
||||
this.dnd.drop(asTreeDragAndDropData(data), targetNode && targetNode.element, targetIndex, originalEvent);
|
||||
}
|
||||
|
||||
onDragEnd(originalEvent: DragEvent): void {
|
||||
if (this.dnd.onDragEnd) {
|
||||
this.dnd.onDragEnd(originalEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function asListOptions<T, TFilterData, TRef>(modelProvider: () => ITreeModel<T, TFilterData, TRef>, options?: IAbstractTreeOptions<T, TFilterData>): IListOptions<ITreeNode<T, TFilterData>> | undefined {
|
||||
@@ -141,12 +161,16 @@ function asListOptions<T, TFilterData, TRef>(modelProvider: () => ITreeModel<T,
|
||||
}
|
||||
},
|
||||
accessibilityProvider: options.accessibilityProvider && {
|
||||
...options.accessibilityProvider,
|
||||
getAriaLabel(e) {
|
||||
return options.accessibilityProvider!.getAriaLabel(e.element);
|
||||
},
|
||||
getAriaLevel(node) {
|
||||
return node.depth;
|
||||
}
|
||||
},
|
||||
getActiveDescendantId: options.accessibilityProvider.getActiveDescendantId && (node => {
|
||||
return options.accessibilityProvider!.getActiveDescendantId!(node.element);
|
||||
})
|
||||
},
|
||||
keyboardNavigationLabelProvider: options.keyboardNavigationLabelProvider && {
|
||||
...options.keyboardNavigationLabelProvider,
|
||||
@@ -211,6 +235,8 @@ export enum RenderIndentGuides {
|
||||
interface ITreeRendererOptions {
|
||||
readonly indent?: number;
|
||||
readonly renderIndentGuides?: RenderIndentGuides;
|
||||
// TODO@joao replace this with collapsible: boolean | 'ondemand'
|
||||
readonly hideTwistiesOfChildlessElements?: boolean;
|
||||
}
|
||||
|
||||
interface IRenderData<TTemplateData> {
|
||||
@@ -244,6 +270,7 @@ class TreeRenderer<T, TFilterData, TRef, TTemplateData> implements IListRenderer
|
||||
private renderedElements = new Map<T, ITreeNode<T, TFilterData>>();
|
||||
private renderedNodes = new Map<ITreeNode<T, TFilterData>, IRenderData<TTemplateData>>();
|
||||
private indent: number = TreeRenderer.DefaultIndent;
|
||||
private hideTwistiesOfChildlessElements: boolean = false;
|
||||
|
||||
private shouldRenderIndentGuides: boolean = false;
|
||||
private renderedIndentGuides = new SetMap<ITreeNode<T, TFilterData>, HTMLDivElement>();
|
||||
@@ -290,6 +317,10 @@ class TreeRenderer<T, TFilterData, TRef, TTemplateData> implements IListRenderer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof options.hideTwistiesOfChildlessElements !== 'undefined') {
|
||||
this.hideTwistiesOfChildlessElements = options.hideTwistiesOfChildlessElements;
|
||||
}
|
||||
}
|
||||
|
||||
renderTemplate(container: HTMLElement): ITreeListTemplateData<TTemplateData> {
|
||||
@@ -309,7 +340,7 @@ class TreeRenderer<T, TFilterData, TRef, TTemplateData> implements IListRenderer
|
||||
}
|
||||
|
||||
const indent = TreeRenderer.DefaultIndent + (node.depth - 1) * this.indent;
|
||||
templateData.twistie.style.marginLeft = `${indent}px`;
|
||||
templateData.twistie.style.paddingLeft = `${indent}px`;
|
||||
templateData.indent.style.width = `${indent + this.indent - 16}px`;
|
||||
|
||||
this.renderTwistie(node, templateData);
|
||||
@@ -365,10 +396,12 @@ class TreeRenderer<T, TFilterData, TRef, TTemplateData> implements IListRenderer
|
||||
this.renderer.renderTwistie(node.element, templateData.twistie);
|
||||
}
|
||||
|
||||
toggleClass(templateData.twistie, 'codicon', node.collapsible);
|
||||
toggleClass(templateData.twistie, 'codicon-chevron-down', node.collapsible);
|
||||
toggleClass(templateData.twistie, 'collapsible', node.collapsible);
|
||||
toggleClass(templateData.twistie, 'collapsed', node.collapsible && node.collapsed);
|
||||
if (node.collapsible && (!this.hideTwistiesOfChildlessElements || node.visibleChildrenCount > 0)) {
|
||||
addClasses(templateData.twistie, 'codicon', 'codicon-chevron-down', 'collapsible');
|
||||
toggleClass(templateData.twistie, 'collapsed', node.collapsed);
|
||||
} else {
|
||||
removeClasses(templateData.twistie, 'codicon', 'codicon-chevron-down', 'collapsible', 'collapsed');
|
||||
}
|
||||
|
||||
if (node.collapsible) {
|
||||
templateData.container.setAttribute('aria-expanded', String(!node.collapsed));
|
||||
@@ -430,12 +463,16 @@ class TreeRenderer<T, TFilterData, TRef, TTemplateData> implements IListRenderer
|
||||
|
||||
nodes.forEach(node => {
|
||||
const ref = model.getNodeLocation(node);
|
||||
const parentRef = model.getParentNodeLocation(ref);
|
||||
try {
|
||||
const parentRef = model.getParentNodeLocation(ref);
|
||||
|
||||
if (node.collapsible && node.children.length > 0 && !node.collapsed) {
|
||||
set.add(node);
|
||||
} else if (parentRef) {
|
||||
set.add(model.getNode(parentRef));
|
||||
if (node.collapsible && node.children.length > 0 && !node.collapsed) {
|
||||
set.add(node);
|
||||
} else if (parentRef) {
|
||||
set.add(model.getNode(parentRef));
|
||||
}
|
||||
} catch {
|
||||
// noop
|
||||
}
|
||||
});
|
||||
|
||||
@@ -601,14 +638,14 @@ class TypeFilterController<T, TFilterData> implements IDisposable {
|
||||
const controls = append(this.domNode, $('.controls'));
|
||||
|
||||
this._filterOnType = !!tree.options.filterOnType;
|
||||
this.filterOnTypeDomNode = append(controls, $<HTMLInputElement>('input.filter'));
|
||||
this.filterOnTypeDomNode = append(controls, $<HTMLInputElement>('input.filter.codicon.codicon-list-selection'));
|
||||
this.filterOnTypeDomNode.type = 'checkbox';
|
||||
this.filterOnTypeDomNode.checked = this._filterOnType;
|
||||
this.filterOnTypeDomNode.tabIndex = -1;
|
||||
this.updateFilterOnTypeTitle();
|
||||
domEvent(this.filterOnTypeDomNode, 'input')(this.onDidChangeFilterOnType, this, this.disposables);
|
||||
|
||||
this.clearDomNode = append(controls, $<HTMLInputElement>('button.clear'));
|
||||
this.clearDomNode = append(controls, $<HTMLInputElement>('button.clear.codicon.codicon-close'));
|
||||
this.clearDomNode.tabIndex = -1;
|
||||
this.clearDomNode.title = localize('clear', "Clear");
|
||||
|
||||
@@ -657,7 +694,7 @@ class TypeFilterController<T, TFilterData> implements IDisposable {
|
||||
|
||||
const onKeyDown = Event.chain(domEvent(this.view.getHTMLElement(), 'keydown'))
|
||||
.filter(e => !isInputElement(e.target as HTMLElement) || e.target === this.filterOnTypeDomNode)
|
||||
.filter(e => e.key !== 'Dead')
|
||||
.filter(e => e.key !== 'Dead' && !/^Media/.test(e.key))
|
||||
.map(e => new StandardKeyboardEvent(e))
|
||||
.filter(this.keyboardNavigationEventFilter || (() => true))
|
||||
.filter(() => this.automaticKeyboardNavigation || this.triggered)
|
||||
@@ -918,7 +955,6 @@ export interface IAbstractTreeOptions<T, TFilterData = void> extends IAbstractTr
|
||||
readonly collapseByDefault?: boolean; // defaults to false
|
||||
readonly filter?: ITreeFilter<T, TFilterData>;
|
||||
readonly dnd?: ITreeDragAndDrop<T>;
|
||||
readonly autoExpandSingleChildren?: boolean;
|
||||
readonly keyboardNavigationEventFilter?: IKeyboardNavigationEventFilter;
|
||||
readonly expandOnlyOnTwistieClick?: boolean | ((e: T) => boolean);
|
||||
readonly additionalScrollHeight?: number;
|
||||
@@ -1385,8 +1421,13 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
|
||||
return this.view.renderHeight;
|
||||
}
|
||||
|
||||
get firstVisibleElement(): T {
|
||||
get firstVisibleElement(): T | undefined {
|
||||
const index = this.view.firstVisibleIndex;
|
||||
|
||||
if (index < 0 || index >= this.view.length) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const node = this.view.element(index);
|
||||
return node.element;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user