text:
'use strict';

import 'vs/css!./media/suggest';
import * as nls from 'vs/nls';
import { createMatches } from 'vs/base/common/filters';
import * as strings from 'vs/base/common/strings';
import { Event, Emitter, chain } from 'vs/base/common/event';
import { onUnexpectedError } from 'vs/base/common/errors';
import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
import { addClass, append, $, hide, removeClass, show, toggleClass, getDomNodePagePosition, hasClass } from 'vs/base/browser/dom';
import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel';
import { IDelegate, IListEvent, IRenderer } from 'vs/base/browser/ui/list/list';
import { List } from 'vs/base/browser/ui/list/listWidget';
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IConfigurationChangedEvent } from 'vs/editor/common/config/editorOptions';
import { ContentWidgetPositionPreference, ICodeEditor, IContentWidget, IContentWidgetPosition } from 'vs/editor/browser/editorBrowser';
import { Context as SuggestContext } from './suggest';
import { ICompletionItem, CompletionModel } from './completionModel';
import { alert } from 'vs/base/browser/ui/aria/aria';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { attachListStyler } from 'vs/platform/theme/common/styler';
import { IThemeService, ITheme, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { registerColor, editorWidgetBackground, listFocusBackground, activeContrastBorder, listHighlightForeground, editorForeground, editorWidgetBorder, focusBorder, textLinkForeground, textCodeBlockBackground } from 'vs/platform/theme/common/colorRegistry';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { MarkdownRenderer } from 'vs/editor/contrib/markdown/markdownRenderer';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { TimeoutTimer, CancelablePromise, createCancelablePromise } from 'vs/base/common/async';
import { CancellationToken } from 'vs/base/common/cancellation';

const sticky = false; // for development purposes
const expandSuggestionDocsByDefault = false;
const maxSuggestionsToShow = 12;

interface ISuggestionTemplateData {
	root: HTMLElement;
	icon: HTMLElement;
	colorspan: HTMLElement;
	highlightedLabel: HighlightedLabel;
	typeLabel: HTMLElement;
	readMore: HTMLElement;
	disposables: IDisposable[];
}

/**
 * Suggest widget colors
 */
export const editorSuggestWidgetBackground = registerColor('editorSuggestWidget.background', { dark: editorWidgetBackground, light: editorWidgetBackground, hc: editorWidgetBackground }, nls.localize('editorSuggestWidgetBackground', 'Background color of the suggest widget.'));
export const editorSuggestWidgetBorder = registerColor('editorSuggestWidget.border', { dark: editorWidgetBorder, light: editorWidgetBorder, hc: editorWidgetBorder }, nls.localize('editorSuggestWidgetBorder', 'Border color of the suggest widget.'));
export const editorSuggestWidgetForeground = registerColor('editorSuggestWidget.foreground', { dark: editorForeground, light: editorForeground, hc: editorForeground }, nls.localize('editorSuggestWidgetForeground', 'Foreground color of the suggest widget.'));
export const editorSuggestWidgetSelectedBackground = registerColor('editorSuggestWidget.selectedBackground', { dark: listFocusBackground, light: listFocusBackground, hc: listFocusBackground }, nls.localize('editorSuggestWidgetSelectedBackground', 'Background color of the selected entry in the suggest widget.'));
export const editorSuggestWidgetHighlightForeground = registerColor('editorSuggestWidget.highlightForeground', { dark: listHighlightForeground, light: listHighlightForeground, hc: listHighlightForeground }, nls.localize('editorSuggestWidgetHighlightForeground', 'Color of the match highlights in the suggest widget.'));

const colorRegExp = /^(#([\da-f]{3}){1,2}|(rgb|hsl)a\(\s*(\d{1,3}%?\s*,\s*){3}(1|0?\.\d+)\)|(rgb|hsl)\(\s*\d{1,3}%?(\s*,\s*\d{1,3}%?){2}\s*\))$/i;
function matchesColor(text: string) {
	return text && text.match(colorRegExp) ? text : null;
}

function canExpandCompletionItem(item: ICompletionItem) {
	if (!item) {
		return false;
	}
	const suggestion = item.suggestion;
	if (suggestion.documentation) {
		return true;
	}
	return (suggestion.detail && suggestion.detail !== suggestion.label);
}

class Renderer implements IRenderer<ICompletionItem, ISuggestionTemplateData> {

	constructor(
		private widget: SuggestWidget,
		private editor: ICodeEditor,
		private triggerKeybindingLabel: string
	) {

	}

	get templateId(): string {
		return 'suggestion';
	}

	renderTemplate(container: HTMLElement): ISuggestionTemplateData {
		const data = <ISuggestionTemplateData>Object.create(null);
		data.disposables = [];
		data.root = container;

		data.icon = append(container, $('.icon'));
		data.colorspan = append(data.icon, $('span.colorspan'));

		const text = append(container, $('.contents'));
		const main = append(text, $('.main'));
		data.highlightedLabel = new HighlightedLabel(main);
		data.disposables.push(data.highlightedLabel);
		data.typeLabel = append(main, $('span.type-label'));

		data.readMore = append(main, $('span.readMore'));
		data.readMore.title = nls.localize('readMore', "Read More...{0}", this.triggerKeybindingLabel);

		const configureFont = () => {
			const configuration = this.editor.getConfiguration();
			const fontFamily = configuration.fontInfo.fontFamily;
			const fontSize = configuration.contribInfo.suggestFontSize || configuration.fontInfo.fontSize;
			const lineHeight = configuration.contribInfo.suggestLineHeight || configuration.fontInfo.lineHeight;
			const fontSizePx = `${fontSize}px`;
			const lineHeightPx = `${lineHeight}px`;

			data.root.style.fontSize = fontSizePx;
			main.style.fontFamily = fontFamily;
			main.style.lineHeight = lineHeightPx;
			data.icon.style.height = lineHeightPx;
			data.icon.style.width = lineHeightPx;
			data.readMore.style.height = lineHeightPx;
			data.readMore.style.width = lineHeightPx;
		};

		configureFont();

		chain<IConfigurationChangedEvent>(this.editor.onDidChangeConfiguration.bind(this.editor))
			.filter(e => e.fontInfo || e.contribInfo)
			.on(configureFont, null, data.disposables);

		return data;
	}

	renderElement(element: ICompletionItem, index: number, templateData: ISuggestionTemplateData): void {
		const data = <ISuggestionTemplateData>templateData;
		const suggestion = (<ICompletionItem>element).suggestion;

		if (canExpandCompletionItem(element)) {
			data.root.setAttribute('aria-label', nls.localize('suggestionWithDetailsAriaLabel', "{0}, suggestion, has details", suggestion.label));
		} else {
			data.root.setAttribute('aria-label', nls.localize('suggestionAriaLabel', "{0}, suggestion", suggestion.label));
		}

		data.icon.className = 'icon ' + suggestion.type;
		data.colorspan.style.backgroundColor = '';

		if (suggestion.type === 'color') {
			let color = matchesColor(suggestion.label) || typeof suggestion.documentation === 'string' && matchesColor(suggestion.documentation);
			if (color) {
				data.icon.className = 'icon customcolor';
				data.colorspan.style.backgroundColor = color;
			}
		}

		data.highlightedLabel.set(suggestion.label, createMatches(element.matches), '', true);
		// data.highlightedLabel.set(`${suggestion.label} <${element.score}=score(${element.word}, ${suggestion.filterText || suggestion.label})>`, createMatches(element.matches));
		data.typeLabel.textContent = (suggestion.detail || '').replace(/\n.*$/m, '');

		if (canExpandCompletionItem(element)) {
			show(data.readMore);
			data.readMore.onmousedown = e => {
				e.stopPropagation();
				e.preventDefault();
			};
			data.readMore.onclick = e => {
				e.stopPropagation();
				e.preventDefault();
				this.widget.toggleDetails();
			};
		} else {
			hide(data.readMore);
			data.readMore.onmousedown = null;
			data.readMore.onclick = null;
		}

	}

	disposeTemplate(templateData: ISuggestionTemplateData): void {
		templateData.disposables = dispose(templateData.disposables);
	}
}

const enum State {
	Hidden,
	Loading,
	Empty,
	Open,
	Frozen,
	Details
}

class SuggestionDetails {

	private el: HTMLElement;
	private close: HTMLElement;
	private scrollbar: DomScrollableElement;
	private body: HTMLElement;
	private header: HTMLElement;
	private type: HTMLElement;
	private docs: HTMLElement;
	private ariaLabel: string;
	private disposables: IDisposable[];
	private renderDisposeable: IDisposable;
	private borderWidth: number = 1;

	constructor(
		container: HTMLElement,
		private widget: SuggestWidget,
		private editor: ICodeEditor,
		private markdownRenderer: MarkdownRenderer,
		private triggerKeybindingLabel: string
	) {
		this.disposables = [];

		this.el = append(container, $('.details'));
		this.disposables.push(toDisposable(() => container.removeChild(this.el)));

		this.body = $('.body');

		this.scrollbar = new DomScrollableElement(this.body, {});
		append(this.el, this.scrollbar.getDomNode());
		this.disposables.push(this.scrollbar);

		this.header = append(this.body, $('.header'));
		this.close = append(this.header, $('span.close'));
		this.close.title = nls.localize('readLess', "Read less...{0}", this.triggerKeybindingLabel);
		this.type = append(this.header, $('p.type'));

		this.docs = append(this.body, $('p.docs'));
		this.ariaLabel = null;

		this.configureFont();

		chain<IConfigurationChangedEvent>(this.editor.onDidChangeConfiguration.bind(this.editor))
			.filter(e => e.fontInfo)
			.on(this.configureFont, this, this.disposables);

		markdownRenderer.onDidRenderCodeBlock(() => this.scrollbar.scanDomNode(), this, this.disposables);
	}

	get element() {
		return this.el;
	}

	render(item: ICompletionItem): void {
		this.renderDisposeable = dispose(this.renderDisposeable);

		if (!item || !canExpandCompletionItem(item)) {
			this.type.textContent = '';
			this.docs.textContent = '';
			addClass(this.el, 'no-docs');
			this.ariaLabel = null;
			return;
		}
		removeClass(this.el, 'no-docs');
		if (typeof item.suggestion.documentation === 'string') {
			removeClass(this.docs, 'markdown-docs');
			this.docs.textContent = item.suggestion.documentation;
		} else {
			addClass(this.docs, 'markdown-docs');
			this.docs.innerHTML = '';
			const renderedContents = this.markdownRenderer.render(item.suggestion.documentation);
			this.renderDisposeable = renderedContents;
			this.docs.appendChild(renderedContents.element);
		}

		if (item.suggestion.detail) {
			this.type.innerText = item.suggestion.detail;
			show(this.type);
		} else {
			this.type.innerText = '';
			hide(this.type);
		}

		this.el.style.height = this.header.offsetHeight + this.docs.offsetHeight + (this.borderWidth * 2) + 'px';

		this.close.onmousedown = e => {
			e.preventDefault();
			e.stopPropagation();
		};
		this.close.onclick = e => {
			e.preventDefault();
			e.stopPropagation();
			this.widget.toggleDetails();
		};

		this.body.scrollTop = 0;
		this.scrollbar.scanDomNode();

		this.ariaLabel = strings.format('{0}\n{1}\n{2}', item.suggestion.label || '', item.suggestion.detail || '', item.suggestion.documentation || '');
	}

	getAriaLabel(): string {
		return this.ariaLabel;
	}

	scrollDown(much = 8): void {
		this.body.scrollTop += much;
	}

	scrollUp(much = 8): void {
		this.body.scrollTop -= much;
	}

	scrollTop(): void {
		this.body.scrollTop = 0;
	}

	scrollBottom(): void {
		this.body.scrollTop = this.body.scrollHeight;
	}

	pageDown(): void {
		this.scrollDown(80);
	}

	pageUp(): void {
		this.scrollUp(80);
	}

	setBorderWidth(width: number): void {
		this.borderWidth = width;
	}

	private configureFont() {
		const configuration = this.editor.getConfiguration();
		const fontFamily = configuration.fontInfo.fontFamily;
		const fontSize = configuration.contribInfo.suggestFontSize || configuration.fontInfo.fontSize;
		const lineHeight = configuration.contribInfo.suggestLineHeight || configuration.fontInfo.lineHeight;
		const fontSizePx = `${fontSize}px`;
		const lineHeightPx = `${lineHeight}px`;

		this.el.style.fontSize = fontSizePx;
		this.type.style.fontFamily = fontFamily;
		this.close.style.height = lineHeightPx;
		this.close.style.width = lineHeightPx;
	}

	dispose(): void {
		this.disposables = dispose(this.disposables);
		this.renderDisposeable = dispose(this.renderDisposeable);
	}
}

export interface ISelectedSuggestion {
	item: ICompletionItem;
	index: number;
	model: CompletionModel;
}

export class SuggestWidget implements IContentWidget, IDelegate<ICompletionItem>, IDisposable {

	private static readonly ID: string = 'editor.widget.suggestWidget';

	static LOADING_MESSAGE: string = nls.localize('suggestWidget.loading', "Loading...");
	static NO_SUGGESTIONS_MESSAGE: string = nls.localize('suggestWidget.noSuggestions', "No suggestions.");

	// Editor.IContentWidget.allowEditorOverflow
	readonly allowEditorOverflow = true;

	private state: State;
	private isAuto: boolean;
	private loadingTimeout: number;
	private currentSuggestionDetails: CancelablePromise<void>;
	private focusedItem: ICompletionItem;
	private ignoreFocusEvents = false;
	private completionModel: CompletionModel;

	private element: HTMLElement;
	private messageElement: HTMLElement;
	private listElement: HTMLElement;
	private details: SuggestionDetails;
	private list: List<ICompletionItem>;
	private listHeight: number;

	private suggestWidgetVisible: IContextKey<boolean>;
	private suggestWidgetMultipleSuggestions: IContextKey<boolean>;
	private suggestionSupportsAutoAccept: IContextKey<boolean>;

	private readonly editorBlurTimeout = new TimeoutTimer();
	private readonly showTimeout = new TimeoutTimer();
	private toDispose: IDisposable[];

	private onDidSelectEmitter = new Emitter<ISelectedSuggestion>();
	private onDidFocusEmitter = new Emitter<ISelectedSuggestion>();
	private onDidHideEmitter = new Emitter<this>();
	private onDidShowEmitter = new Emitter<this>();

	readonly onDidSelect: Event<ISelectedSuggestion> = this.onDidSelectEmitter.event;
	readonly onDidFocus: Event<ISelectedSuggestion> = this.onDidFocusEmitter.event;
	readonly onDidHide: Event<this> = this.onDidHideEmitter.event;
	readonly onDidShow: Event<this> = this.onDidShowEmitter.event;

	private readonly maxWidgetWidth = 660;
	private readonly listWidth = 330;
	private storageService: IStorageService;
	private detailsFocusBorderColor: string;
	private detailsBorderColor: string;

	private storageServiceAvailable: boolean = true;
	private expandSuggestionDocs: boolean = false;

	private firstFocusInCurrentList: boolean = false;

	constructor(
		private editor: ICodeEditor,
		@ITelemetryService private telemetryService: ITelemetryService,
		@IContextKeyService contextKeyService: IContextKeyService,
		@IThemeService themeService: IThemeService,
		@IStorageService storageService: IStorageService,
		@IKeybindingService keybindingService: IKeybindingService,
		@IModeService modeService: IModeService,
		@IOpenerService openerService: IOpenerService
	) {
		const kb = keybindingService.lookupKeybinding('editor.action.triggerSuggest');
		const triggerKeybindingLabel = !kb ? '' : ` (${kb.getLabel()})`;
		const markdownRenderer = new MarkdownRenderer(editor, modeService, openerService);

		this.isAuto = false;
		this.focusedItem = null;
		this.storageService = storageService;

		if (this.expandDocsSettingFromStorage() === undefined) {
			this.storageService.store('expandSuggestionDocs', expandSuggestionDocsByDefault, StorageScope.GLOBAL);
			if (this.expandDocsSettingFromStorage() === undefined) {
				this.storageServiceAvailable = false;
			}
		}

		this.element = $('.editor-widget.suggest-widget');
		if (!this.editor.getConfiguration().contribInfo.iconsInSuggestions) {
			addClass(this.element, 'no-icons');
		}

		this.messageElement = append(this.element, $('.message'));
		this.listElement = append(this.element, $('.tree'));
		this.details = new SuggestionDetails(this.element, this, this.editor, markdownRenderer, triggerKeybindingLabel);

		let renderer = new Renderer(this, this.editor, triggerKeybindingLabel);

		this.list = new List(this.listElement, this, [renderer], {
			useShadows: false,
			selectOnMouseDown: true,
			focusOnMouseDown: false,
			openController: { shouldOpen: () => false }
		});

		this.toDispose = [
			attachListStyler(this.list, themeService, {
				listInactiveFocusBackground: editorSuggestWidgetSelectedBackground,
				listInactiveFocusOutline: activeContrastBorder
			}),
			themeService.onThemeChange(t => this.onThemeChange(t)),
			editor.onDidBlurEditorText(() => this.onEditorBlur()),
			editor.onDidLayoutChange(() => this.onEditorLayoutChange()),
			this.list.onSelectionChange(e => this.onListSelection(e)),
			this.list.onFocusChange(e => this.onListFocus(e)),
			this.editor.onDidChangeCursorSelection(() => this.onCursorSelectionChanged())
		];

		this.suggestWidgetVisible = SuggestContext.Visible.bindTo(contextKeyService);
		this.suggestWidgetMultipleSuggestions = SuggestContext.MultipleSuggestions.bindTo(contextKeyService);
		this.suggestionSupportsAutoAccept = SuggestContext.AcceptOnKey.bindTo(contextKeyService);

		this.editor.addContentWidget(this);
		this.setState(State.Hidden);

		this.onThemeChange(themeService.getTheme());
	}

	private onCursorSelectionChanged(): void {
		if (this.state === State.Hidden) {
			return;
		}

		this.editor.layoutContentWidget(this);
	}

	private onEditorBlur(): void {
		if (sticky) {
			return;
		}

		this.editorBlurTimeout.cancelAndSet(() => {
			if (!this.editor.hasTextFocus()) {
				this.setState(State.Hidden);
			}
		}, 150);
	}

	private onEditorLayoutChange(): void {
		if ((this.state === State.Open || this.state === State.Details) && this.expandDocsSettingFromStorage()) {
			this.expandSideOrBelow();
		}
	}

	private onListSelection(e: IListEvent<ICompletionItem>): void {
		if (!e.elements.length) {
			return;
		}

		const item = e.elements[0];
		const index = e.indexes[0];
		item.resolve(CancellationToken.None).then(() => {
			this.onDidSelectEmitter.fire({ item, index, model: this.completionModel });
			alert(nls.localize('suggestionAriaAccepted', "{0}, accepted", item.suggestion.label));
			this.editor.focus();
		});
	}

	private _getSuggestionAriaAlertLabel(item: ICompletionItem): string {
		if (canExpandCompletionItem(item)) {
			return nls.localize('ariaCurrentSuggestionWithDetails', "{0}, suggestion, has details", item.suggestion.label);
		} else {
			return nls.localize('ariaCurrentSuggestion', "{0}, suggestion", item.suggestion.label);
		}
	}

	private _lastAriaAlertLabel: string;
	private _ariaAlert(newAriaAlertLabel: string): void {
		if (this._lastAriaAlertLabel === newAriaAlertLabel) {
			return;
		}
		this._lastAriaAlertLabel = newAriaAlertLabel;
		if (this._lastAriaAlertLabel) {
			alert(this._lastAriaAlertLabel);
		}
	}

	private onThemeChange(theme: ITheme) {
		let backgroundColor = theme.getColor(editorSuggestWidgetBackground);
		if (backgroundColor) {
			this.listElement.style.backgroundColor = backgroundColor.toString();
			this.details.element.style.backgroundColor = backgroundColor.toString();
			this.messageElement.style.backgroundColor = backgroundColor.toString();
		}
		let borderColor = theme.getColor(editorSuggestWidgetBorder);
		if (borderColor) {
			this.listElement.style.borderColor = borderColor.toString();
			this.details.element.style.borderColor = borderColor.toString();
			this.messageElement.style.borderColor = borderColor.toString();
			this.detailsBorderColor = borderColor.toString();
		}
		let focusBorderColor = theme.getColor(focusBorder);
		if (focusBorderColor) {
			this.detailsFocusBorderColor = focusBorderColor.toString();
		}
		this.details.setBorderWidth(theme.type === 'hc' ? 2 : 1);
	}

	private onListFocus(e: IListEvent<ICompletionItem>): void {
		if (this.ignoreFocusEvents) {
			return;
		}

		if (!e.elements.length) {
			if (this.currentSuggestionDetails) {
				this.currentSuggestionDetails.cancel();
				this.currentSuggestionDetails = null;
				this.focusedItem = null;
			}

			this._ariaAlert(null);
			return;
		}

		const item = e.elements[0];
		this._ariaAlert(this._getSuggestionAriaAlertLabel(item));

		this.firstFocusInCurrentList = !this.focusedItem;
		if (item === this.focusedItem) {
			return;
		}

		if (this.currentSuggestionDetails) {
			this.currentSuggestionDetails.cancel();
			this.currentSuggestionDetails = null;
		}

		const index = e.indexes[0];

		this.suggestionSupportsAutoAccept.set(!item.suggestion.noAutoAccept);

		this.focusedItem = item;

		this.list.reveal(index);

		this.currentSuggestionDetails = createCancelablePromise(token => item.resolve(token));

		this.currentSuggestionDetails.then(() => {
			// item can have extra information, so re-render
			this.ignoreFocusEvents = true;
			this.list.splice(index, 1, [item]);
			this.list.setFocus([index]);
			this.ignoreFocusEvents = false;

			if (this.expandDocsSettingFromStorage()) {
				this.showDetails();
			} else {
				removeClass(this.element, 'docs-side');
			}
		}).catch(onUnexpectedError).then(() => this.currentSuggestionDetails = null);

		// emit an event
		this.onDidFocusEmitter.fire({ item, index, model: this.completionModel });
	}

	private setState(state: State): void {
		if (!this.element) {
			return;
		}

		const stateChanged = this.state !== state;
		this.state = state;

		toggleClass(this.element, 'frozen', state === State.Frozen);

		switch (state) {
			case State.Hidden:
				hide(this.messageElement, this.details.element, this.listElement);
				this.hide();
				this.listHeight = 0;
				if (stateChanged) {
					this.list.splice(0, this.list.length);
				}
				this.focusedItem = null;
				break;
			case State.Loading:
				this.messageElement.textContent = SuggestWidget.LOADING_MESSAGE;
				hide(this.listElement, this.details.element);
				show(this.messageElement);
				removeClass(this.element, 'docs-side');
				this.show();
				this.focusedItem = null;
				break;
			case State.Empty:
				this.messageElement.textContent = SuggestWidget.NO_SUGGESTIONS_MESSAGE;
				hide(this.listElement, this.details.element);
				show(this.messageElement);
				removeClass(this.element, 'docs-side');
				this.show();
				this.focusedItem = null;
				break;
			case State.Open:
				hide(this.messageElement);
				show(this.listElement);
				this.show();
				break;
			case State.Frozen:
				hide(this.messageElement);
				show(this.listElement);
				this.show();
				break;
			case State.Details:
				hide(this.messageElement);
				show(this.details.element, this.listElement);
				this.show();
				this._ariaAlert(this.details.getAriaLabel());
				break;
		}
	}

	showTriggered(auto: boolean) {
		if (this.state !== State.Hidden) {
			return;
		}

		this.isAuto = !!auto;

		if (!this.isAuto) {
			this.loadingTimeout = setTimeout(() => {
				this.loadingTimeout = null;
				this.setState(State.Loading);
			}, 50);
		}
	}

	showSuggestions(completionModel: CompletionModel, selectionIndex: number, isFrozen: boolean, isAuto: boolean): void {
		if (this.loadingTimeout) {
			clearTimeout(this.loadingTimeout);
			this.loadingTimeout = null;
		}

		if (this.completionModel !== completionModel) {
			this.completionModel = completionModel;
		}

		if (isFrozen && this.state !== State.Empty && this.state !== State.Hidden) {
			this.setState(State.Frozen);
			return;
		}

		let visibleCount = this.completionModel.items.length;

		const isEmpty = visibleCount === 0;
		this.suggestWidgetMultipleSuggestions.set(visibleCount > 1);

		if (isEmpty) {
			if (isAuto) {
				this.setState(State.Hidden);
			} else {
				this.setState(State.Empty);
			}

			this.completionModel = null;

		} else {
			const { stats } = this.completionModel;
			stats['wasAutomaticallyTriggered'] = !!isAuto;
			/* __GDPR__
				"suggestWidget" : {
					"wasAutomaticallyTriggered" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
					"${include}": [
						"${ICompletionStats}",
						"${EditorTelemetryData}"
					]
				}
			*/
			this.telemetryService.publicLog('suggestWidget', { ...stats, ...this.editor.getTelemetryData() });

			this.list.splice(0, this.list.length, this.completionModel.items);

			if (isFrozen) {
				this.setState(State.Frozen);
			} else {
				this.setState(State.Open);
			}

			this.list.reveal(selectionIndex, selectionIndex);
			this.list.setFocus([selectionIndex]);

			// Reset focus border
			if (this.detailsBorderColor) {
				this.details.element.style.borderColor = this.detailsBorderColor;
			}
		}
	}

	selectNextPage(): boolean {
		switch (this.state) {
			case State.Hidden:
				return false;
			case State.Details:
				this.details.pageDown();
				return true;
			case State.Loading:
				return !this.isAuto;
			default:
				this.list.focusNextPage();
				return true;
		}
	}

	selectNext(): boolean {
		switch (this.state) {
			case State.Hidden:
				return false;
			case State.Loading:
				return !this.isAuto;
			default:
				this.list.focusNext(1, true);
				return true;
		}
	}

	selectLast(): boolean {
		switch (this.state) {
			case State.Hidden:
				return false;
			case State.Details:
				this.details.scrollBottom();
				return true;
			case State.Loading:
				return !this.isAuto;
			default:
				this.list.focusLast();
				return true;
		}
	}

	selectPreviousPage(): boolean {
		switch (this.state) {
			case State.Hidden:
				return false;
			case State.Details:
				this.details.pageUp();
				return true;
			case State.Loading:
				return !this.isAuto;
			default:
				this.list.focusPreviousPage();
				return true;
		}
	}

	selectPrevious(): boolean {
		switch (this.state) {
			case State.Hidden:
				return false;
			case State.Loading:
				return !this.isAuto;
			default:
				this.list.focusPrevious(1, true);
				return false;
		}
	}

	selectFirst(): boolean {
		switch (this.state) {
			case State.Hidden:
				return false;
			case State.Details:
				this.details.scrollTop();
				return true;
			case State.Loading:
				return !this.isAuto;
			default:
				this.list.focusFirst();
				return true;
		}
	}

	getFocusedItem(): ISelectedSuggestion {
		if (this.state !== State.Hidden
			&& this.state !== State.Empty
			&& this.state !== State.Loading) {

			return {
				item: this.list.getFocusedElements()[0],
				index: this.list.getFocus()[0],
				model: this.completionModel
			};
		}
		return undefined;
	}

	toggleDetailsFocus(): void {
		if (this.state === State.Details) {
			this.setState(State.Open);
			if (this.detailsBorderColor) {
				this.details.element.style.borderColor = this.detailsBorderColor;
			}
		} else if (this.state === State.Open && this.expandDocsSettingFromStorage()) {
			this.setState(State.Details);
			if (this.detailsFocusBorderColor) {
				this.details.element.style.borderColor = this.detailsFocusBorderColor;
			}
		}
		/* __GDPR__
			"suggestWidget:toggleDetailsFocus" : {
				"${include}": [
					"${EditorTelemetryData}"
				]
			}
		*/
		this.telemetryService.publicLog('suggestWidget:toggleDetailsFocus', this.editor.getTelemetryData());
	}

	toggleDetails(): void {
		if (!canExpandCompletionItem(this.list.getFocusedElements()[0])) {
			return;
		}

		if (this.expandDocsSettingFromStorage()) {
			this.updateExpandDocsSetting(false);
			hide(this.details.element);
			removeClass(this.element, 'docs-side');
			removeClass(this.element, 'docs-below');
			this.editor.layoutContentWidget(this);
			/* __GDPR__
				"suggestWidget:collapseDetails" : {
					"${include}": [
						"${EditorTelemetryData}"
					]
				}
			*/
			this.telemetryService.publicLog('suggestWidget:collapseDetails', this.editor.getTelemetryData());
		} else {
			if (this.state !== State.Open && this.state !== State.Details) {
				return;
			}

			this.updateExpandDocsSetting(true);
			this.showDetails();
			/* __GDPR__
				"suggestWidget:expandDetails" : {
					"${include}": [
						"${EditorTelemetryData}"
					]
				}
			*/
			this.telemetryService.publicLog('suggestWidget:expandDetails', this.editor.getTelemetryData());
		}

	}

	showDetails(): void {
		this.expandSideOrBelow();

		show(this.details.element);
		this.details.render(this.list.getFocusedElements()[0]);
		this.details.element.style.maxHeight = this.maxWidgetHeight + 'px';

		// Reset margin-top that was set as Fix for #26416
		this.listElement.style.marginTop = '0px';

		// with docs showing up widget width/height may change, so reposition the widget
		this.editor.layoutContentWidget(this);

		this.adjustDocsPosition();

		this.editor.focus();

		this._ariaAlert(this.details.getAriaLabel());
	}

	private show(): void {
		const newHeight = this.updateListHeight();
		if (newHeight !== this.listHeight) {
			this.editor.layoutContentWidget(this);
			this.listHeight = newHeight;
		}

		this.suggestWidgetVisible.set(true);

		this.showTimeout.cancelAndSet(() => {
			addClass(this.element, 'visible');
			this.onDidShowEmitter.fire(this);
		}, 100);
	}

	private hide(): void {
		this.suggestWidgetVisible.reset();
		this.suggestWidgetMultipleSuggestions.reset();
		removeClass(this.element, 'visible');
	}

	hideWidget(): void {
		clearTimeout(this.loadingTimeout);
		this.setState(State.Hidden);
		this.onDidHideEmitter.fire(this);
	}

	getPosition(): IContentWidgetPosition {
		if (this.state === State.Hidden) {
			return null;
		}

		return {
			position: this.editor.getPosition(),
			preference: [ContentWidgetPositionPreference.BELOW, ContentWidgetPositionPreference.ABOVE]
		};
	}

	getDomNode(): HTMLElement {
		return this.element;
	}

	getId(): string {
		return SuggestWidget.ID;
	}

	private updateListHeight(): number {
		let height = 0;

		if (this.state === State.Empty || this.state === State.Loading) {
			height = this.unfocusedHeight;
		} else {
			const suggestionCount = this.list.contentHeight / this.unfocusedHeight;
			height = Math.min(suggestionCount, maxSuggestionsToShow) * this.unfocusedHeight;
		}

		this.element.style.lineHeight = `${this.unfocusedHeight}px`;
		this.listElement.style.height = `${height}px`;
		this.list.layout(height);
		return height;
	}

	private adjustDocsPosition() {
		const lineHeight = this.editor.getConfiguration().fontInfo.lineHeight;
		const cursorCoords = this.editor.getScrolledVisiblePosition(this.editor.getPosition());
		const editorCoords = getDomNodePagePosition(this.editor.getDomNode());
		const cursorX = editorCoords.left + cursorCoords.left;
		const cursorY = editorCoords.top + cursorCoords.top + cursorCoords.height;
		const widgetCoords = getDomNodePagePosition(this.element);
		const widgetX = widgetCoords.left;
		const widgetY = widgetCoords.top;

		if (widgetX < cursorX - this.listWidth) {
			// Widget is too far to the left of cursor, swap list and docs
			addClass(this.element, 'list-right');
		} else {
			removeClass(this.element, 'list-right');
		}

		// Compare top of the cursor (cursorY - lineheight) with widgetTop to determine if
		// margin-top needs to be applied on list to make it appear right above the cursor
		// Cannot compare cursorY directly as it may be a few decimals off due to zoooming
		if (hasClass(this.element, 'docs-side')
			&& cursorY - lineHeight > widgetY
			&& this.details.element.offsetHeight > this.listElement.offsetHeight) {

			// Fix for #26416
			// Docs is bigger than list and widget is above cursor, apply margin-top so that list appears right above cursor
			this.listElement.style.marginTop = `${this.details.element.offsetHeight - this.listElement.offsetHeight}px`;
		}
	}

	private expandSideOrBelow() {
		if (!canExpandCompletionItem(this.focusedItem) && this.firstFocusInCurrentList) {
			removeClass(this.element, 'docs-side');
			removeClass(this.element, 'docs-below');
			return;
		}

		let matches = this.element.style.maxWidth.match(/(\d+)px/);
		if (!matches || Number(matches[1]) < this.maxWidgetWidth) {
			addClass(this.element, 'docs-below');
			removeClass(this.element, 'docs-side');
		} else if (canExpandCompletionItem(this.focusedItem)) {
			addClass(this.element, 'docs-side');
			removeClass(this.element, 'docs-below');
		}
	}

	// Heights

	private get maxWidgetHeight(): number {
		return this.unfocusedHeight * maxSuggestionsToShow;
	}

	private get unfocusedHeight(): number {
		const configuration = this.editor.getConfiguration();
		return configuration.contribInfo.suggestLineHeight || configuration.fontInfo.lineHeight;
	}

	// IDelegate

	getHeight(element: ICompletionItem): number {
		return this.unfocusedHeight;
	}

	getTemplateId(element: ICompletionItem): string {
		return 'suggestion';
	}

	// Monaco Editor does not have a storage service
	private expandDocsSettingFromStorage(): boolean {
		if (this.storageServiceAvailable) {
			return this.storageService.getBoolean('expandSuggestionDocs', StorageScope.GLOBAL);
		} else {
			return this.expandSuggestionDocs;
		}
	}

	// Monaco Editor does not have a storage service
	private updateExpandDocsSetting(value: boolean) {
		if (this.storageServiceAvailable) {
			this.storageService.store('expandSuggestionDocs', value, StorageScope.GLOBAL);
		} else {
			this.expandSuggestionDocs = value;
		}
	}

	dispose(): void {
		this.state = null;
		this.suggestionSupportsAutoAccept = null;
		this.currentSuggestionDetails = null;
		this.focusedItem = null;
		this.element = null;
		this.messageElement = null;
		this.listElement = null;
		this.details.dispose();
		this.details = null;
		this.list.dispose();
		this.list = null;
		this.toDispose = dispose(this.toDispose);
		if (this.loadingTimeout) {
			clearTimeout(this.loadingTimeout);
			this.loadingTimeout = null;
		}

		this.editorBlurTimeout.dispose();
		this.showTimeout.dispose();
	}
}

registerThemingParticipant((theme, collector) => {
	let matchHighlight = theme.getColor(editorSuggestWidgetHighlightForeground);
	if (matchHighlight) {
		collector.addRule(`.monaco-editor .suggest-widget .monaco-list .monaco-list-row .monaco-highlighted-label .highlight { color: ${matchHighlight}; }`);
	}
	let foreground = theme.getColor(editorSuggestWidgetForeground);
	if (foreground) {
		collector.addRule(`.monaco-editor .suggest-widget { color: ${foreground}; }`);
	}

	const link = theme.getColor(textLinkForeground);
	if (link) {
		collector.addRule(`.monaco-editor .suggest-widget a { color: ${link}; }`);
	}

	let codeBackground = theme.getColor(textCodeBlockBackground);
	if (codeBackground) {
		collector.addRule(`.monaco-editor .suggest-widget code { background-color: ${codeBackground}; }`);
	}
});


VENICE, Italy – Jonathan Demme's first experience hearing the music of Italy's Enzo Avitabile was such perfection that the Oscar-winning filmmaker said no one would believe it if he put it on film.
"I can recall this moment very vividly because it was just a very impactive life moment," Demme said in an interview at the Venice Film Festival, where his movie "Enzo Avitabile Music Life" premiered out of competition.
Demme was in New York City driving toward the George Washington Bridge, on his way home after a long day working, when he flipped on the radio and heard Avitabile being announced — picture-perfect timing.
"And now, I am seeing the bridge and the highway and the cars speeding by, with this extraordinary music, unlike anything I'd ever heard before," Demme said. "'I loved his voice, a tremendous rhythmic presence. Suddenly my life had gotten thrilling. I was in some adventure film."
Demme said immediately got his hands on all of Avitabile's music, which melds jazz with pop music and Afro-American beats and sacred chants.
And when invited to a film festival in Naples, he asked the organizer to arrange a meeting with the Neapolitan musician. The organizer did more than that: he proposed they make a film together, and rustled up financing from Italy's RAI, the state broadcaster which has a cinema arm.
Demme, best known for his Oscar-winning movie "Silence of the Lambs" as well as "Philadelphia" and "Rachel Getting Married," had previously made music documentaries about the Talking Heads and Neil Young — so it was easy to say yes.
"I believe that filming great live music is as pure a filmmaking experience as exists," Demme said. "Because you are not doing a documentary, you are not creating an artificial reality. It's you channeling this completely creative process that's happening right now in front of the lens."
As a filmmaker, he said the challenge is to capture on film the relationships between the musicians as they play, and to get as long a shot as possible without editing.
The Avitabile film, shot entirely in Naples, centers around jam sessions with a dozen world musicians at a Baroque church along with scenes from Avitabile's life, his middle class Naples apartment and the nitty gritty of his hometown of Marianella on the outskirts of Naples.
"I did have a lot of confidence in the visual power that lives in Naples," Demme said. "I was capturing Enzo's Naples," which he called "a tremendous melting pot."
The film is sure to draw wider attention to Avitabile, 57, who said jukeboxes were his first contact such musicians as James Brown, with whom he eventually collaborated. Avitabile trained at a music conservatory, but has avoided conforming to industry standards.
The Demme film project was "something unexpected," Avitabile said, adding, "From this grew a great friendship."
Demme said he can envision future collaborations with Avitabile.
"Conceivably there could be a soundtrack relationship someday," he said.


text:
HRC VEX Teams Triumph at States!
The Haslett Robotics Club (HRC) is pleased to announce that it had a strong showing at the VEX Robotics State Championship at MSU on February 22nd, 2015. The competition saw 59 of the best teams from around the state competing. All four the club's VEX teams competed and performed admirably.
During the competition, all four HRC teams made it to the elimination rounds. The final round had two of our teams, the Dragons and the Raptors, battling it out on opposing alliances. In the end, the Raptors came out on top as Tournament Champions.
The Haslett Raptors also won the tournament's highest honor, the coveted Excellence Award, recognizing them as the top overall team in the state. Additionally, the Raptors won the Robotics Skills Award with a score high enough to break the previous State record. With these awards and as reigning World Champions, the Raptors team qualifies in four different ways to advance to Worlds. (We think they might really, really want to go)
The Haslett Dragons, as tournament finalists, qualified along with the Raptors to compete at the World Championship tournament in Louisville, KY in April! This is the second consecutive year, Haslett has two teams advancing to Worlds. Way to go Dragons! We wish them continuing success at Worlds.
The Haslett Vortex, despite technical problems, persevered to the quarter finals of the tournament. Their impressive robot design incorporated very advanced engineering, earning them the Judges Award, which recognizes teamwork, sportsmanship, and the high quality of their robot. Having competed at Worlds last year, they are understandably disappointed to not qualify again, but the Vortex are to be congratulated for their successful season taking them to the quarter finals at States! They have huge potential and we can't wait to see what they show us next year.
Speaking of potential, our brand new middle school team, the Haslett Minotaurs has had a fantastic inaugural season. They went all the way to the semi-finals in the middle school division at the State tournament. They also scored well in both the Robotics Skills challenges. Very impressive job Minotaurs!
The club is very proud of the four VEX teams and its coaches, Claus Buchholz, Kim Schramm, and Mike Scott.
Finally, a big shout out of thanks to the younger Halsett Robotics Club team members and coaches, David Rothstein, Todd Wilson and Christina DeJong. These teams, which consist of 9 to 14 year old students from Haslett and the surrounding area, compete in the FIRST Lego League. Their assistance in running the VEX competition exemplifies our club's collaborative spirit and also helped expose the kids to a complex and exciting new robotics platform. The VEX state tournament organizers are much appreciative of our FLL teams' help.
For additional reference, the club was mentioned in a segment on WLNS:
http://wlns.com/2015/02/23/haslett-teams-advance-to-world-championship-for-vex-robotics/

redpajama_set_name: RedPajamaCommonCrawl


text:
A biography and life work of martin luther king junior an american social activist
Articles for students to write about
Danger conformity
Singers solution to world poverty essays
The mind in reading spins a web from scene to scene, compounds a background from apples falling, and the toll of a church bell, and an owl's fantastic flight which keeps the play together.
Mormon Channel releases gritty videos of real addicts in recovery process Deseret News - Utah August 31, - Relevance: The invitation was fiercely attacked by leading intellectuals and organisations in German media, with an article in Der Spiegel comparing Singer's positions to Nazism.
Intercultural Communication Theory COM 3 credits An overview of the theories about intercultural communication between people of different cultures. This packing up and going off, exploring deserts and catching fevers, settling in India for a lifetime, penetrating even to China and then returning to lead a parochial life at Edmonton, tumbles and tosses upon the dusty floor like an uneasy sea, so restless the English are, with the waves at their very door.
The author of the book subsequently wrote to the editor saying that the article was so good that he would greatly like to have the typescript of it if the editor would give it to him. It became an important industrial center in the nineteenth century, but by the mid-twentieth century its industries had declined and much of its middle class population had relocated to the suburbs.
The physical environment has had significant effects on regional cultures. Logging or grazing on these lands is regulated and requires permits.
Does this little figure advancing through beauty, through death, to the economical, powerful and efficient future when houses will be cleansed by a puff of hot wind satisfy you? Indeed, his wife's dowry of two thousand pounds had gone to pay off the debts of his youth.
This was well understood by classical conservatives like Hume and Edmund Burke. But when the door shuts on us, all that vanishes. If she had lived, there is no doubt that she would have made large alterations and revisions in nearly all these essays before allowing them to appear in volume form.
That ends up meaning something very specific indeed, especially in democracies like Athens, with an Assembly of the male citizens: It was useless to try to do anything.
Historical perspective on film theory and insight into its intersection with other disciplines. Warhol's art documented icons of American life such as Cambell's soup cans and Marilyn Monroe.
I have not hesitated to do this, since I always revised the mss. Some Americans, particularly in the South, eat hopping john, a dish made with black-eyed peas, to bring good luck in the New Year.
Religious humanism acknowledges that the human condition may involve something more, but then this is split according to the degree of control and rationalism that is expected.
And we see it through the eyes of somebody who is leaning over the Embankment on a summer evening, without a care in the world. Standard English grammar and pronunciation are taught by English teachers in public schools. If a religious humanism can become essentially rationalistic, it is central to note what it does regard as religious and how this differs from the more intrinsic and genuine requirements of religion.
Fundamentals of Multimedia DIG 4 credits This production course explores a range of ideas and processes incorporated in multimedia projects. This has been especially damaging in liberal Christianity and Judaism. These donations are tax-deductible and are a popular hedge among the wealthy against income and estate taxes.
Perhaps that it was not a whole. Interestingly, Florida and Arizona, which have the death penalty, have the highest rates of violent crime in the country. Yet the power was there all the same, massed outside indifferent, impersonal, not attending to anything in particular. There are a few lights in the bedrooms of great peers returned from Court, of silk-stockinged footmen, of dowagers who have pressed the hands of statesmen.
These programs, which were intended to provide a buffer against the inevitable downturns of economic cycles, were also a response to serious social unrest, including strikes and socialist organizing.
The stars shone perfectly steadily. As we step out of the house on a fine evening between four and six, we shed the self our friends know us by and become part of that vast republican army of anonymous trampers, whose society is so agreeable after the solitude of one's own room.
RTV with minimum grade of "C" Investigation of video as an experimental art form through exploratory production exercises. Female occupations both in the home and in the workplace are valued less than men's.
He quoted author Alison Mood's startling statistics from a report she wrote, which was released on fishcount. Guthrie's; and since they all differ back we must go to Shakespeare. Suddenly, from an unexpected quarter, help appeared.
Ketton-Cremer says, is always changing about Walpole. Stainless and boundless rest; space unlimited; untrodden grass; wild birds flying hills whose smooth uprise continue that wild flight.Cody Choi, visual artist and cultural theorist was born in Seoul in He attended Korea University Sociology major, Korea and Art Center College of Design, Pasadena, California, USA.
In the essay "The Singer Solution to World Poverty," philosopher Peter Singer addresses the issue of poverty by suggesting Americans give away most of their income to aid those in need. Singer believes that withholding income is the equivalence of letting a child starve to death.
In the New York Times Article " the Singer Solution to World Poverty" the author Peter Singer argues that there is no reason why Americans don't donate money to the needy when they can afford countless of luxury that are not essential to the preservation of their lives and health.
Popular Essays. Overpopulation: Earth's Destruction. The writer behind "Singers Solution to World Poverty" advocates that U.S.
citizens give away the majority of their dispensable income in order to end global suffering. Peter Singer makes numerous assumptions within his proposal about world poverty, and they are founded on the principle that.
The Solution to World Poverty* PETER SINGER *From "The Singer Solution to World Poverty." The New York Times Magazine (). Using a number of examples to make his case, Peter Singer argues that whatever money.
The Poor People's Campaign, or Poor People's March on Washington, was a effort to gain economic justice for poor people in the United cheri197.com was organized by Martin Luther King, Jr.
and the Southern Christian Leadership Conference (SCLC), and carried out under the leadership of Ralph Abernathy in the wake of King's assassination. The campaign demanded economic and human rights .
Conclusion examples for compare and contrast essays for kids
Ge business planning grid
Describe the potential effects of discrimination
Social mktg
Winterbourne view hospital report
Career objectives mba essay
Character analysis reverend hale crucible
Write about role of science in our daily life
The life of pastoral nomads tribes during british rule in india
The structure and types of remotely operated vehicle