Skip to content

Commit

Permalink
Improved QuickInput/InputBox API's. Partially fixes: #5109
Browse files Browse the repository at this point in the history
Signed-off-by: Josh Pinkney <[email protected]>
  • Loading branch information
JPinkney committed Jun 4, 2019
1 parent df80217 commit 3c29097
Show file tree
Hide file tree
Showing 9 changed files with 711 additions and 32 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Breaking changes:
- [plugin] 'Hosted mode' extracted in `plugin-dev` extension
- [core] `scheme` is mandatory for URI
- `URI.withoutScheme` is removed, in order to get a path use `URI.path`
- [plugin-ext] improved QuickInput and InputBox API's

## v0.7.0

Expand Down
129 changes: 126 additions & 3 deletions packages/core/src/browser/quick-open/quick-input-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,52 @@
********************************************************************************/

import { inject, injectable } from 'inversify';
import { QuickOpenService } from './quick-open-service';
import { QuickOpenService, TitleButton } from './quick-open-service';
import { QuickOpenItem, QuickOpenMode } from './quick-open-model';
import { Deferred } from '../../common/promise-util';
import { MaybePromise } from '../../common/types';
import { MessageType } from '../../common/message-service-protocol';
import { Emitter, Event } from '../../common/event';
import { InputTitleBar } from './quick-input-title-bar';
import { ThemeService } from '../theming';

export interface QuickInputOptions {

/**
* Show the progress indicator if true
*/
busy?: boolean

/**
* Allow user input
*/
enabled?: boolean;

/**
* Current step count
*/
step?: number | undefined

/**
* The title of the input
*/
title?: string | undefined

/**
* Total number of steps
*/
totalSteps?: number | undefined

/**
* Buttons that are displayed on the title panel
*/
buttons?: ReadonlyArray<TitleButton>

/**
* Text for when there is a problem with the current input value
*/
validationMessage?: string | undefined;

/**
* The prefill value.
*/
Expand Down Expand Up @@ -64,15 +102,35 @@ export class QuickInputService {
@inject(QuickOpenService)
protected readonly quickOpenService: QuickOpenService;

@inject(ThemeService)
protected readonly themeService: ThemeService;

protected _titlePanel: InputTitleBar;
protected titleBarContainer: HTMLElement;
protected titleElement: HTMLElement | undefined;

constructor() {
this._titlePanel = new InputTitleBar();
this.createTitleBarContainer();
}

open(options: QuickInputOptions): Promise<string | undefined> {
const result = new Deferred<string | undefined>();
const prompt = this.createPrompt(options.prompt);
let label = prompt;
let currentText = '';
const validateInput = options && options.validateInput;

this.titlePanel.title = options.title;
this.titlePanel.step = options.step;
this.titlePanel.totalSteps = options.totalSteps;
this.titlePanel.buttons = options.buttons;
this.removeTitleElement();
this.titlePanel.isAttached = false;

this.quickOpenService.open({
onType: async (lookFor, acceptor) => {
const error = validateInput ? await validateInput(lookFor) : undefined;
const error = validateInput && lookFor !== undefined ? await validateInput(lookFor) : undefined;
label = error || prompt;
if (error) {
this.quickOpenService.showDecoration(MessageType.Error);
Expand All @@ -97,11 +155,71 @@ export class QuickInputService {
placeholder: options.placeHolder,
password: options.password,
ignoreFocusOut: options.ignoreFocusOut,
onClose: () => result.resolve(undefined)
busy: options.busy,
enabled: options.enabled,
onClose: () => {
result.resolve(undefined);
this.titlePanel.dispose();
this.onDidHideEmitter.fire(undefined);
this.removeTitleElement();
this.createTitleBarContainer();
}
});
this.attachTitleBarIfNeeded();
if (this.titlePanel.shouldShowTitleBar()) {
this.quickOpenService.widgetNode.prepend(this.titleBarContainer);
}
return result.promise;
}

private createTitleBarContainer(): void {
this.titleBarContainer = document.createElement('div');
this.titleBarContainer.style.backgroundColor = 'var(--theia-menu-color0)';
}

setStep(step: number | undefined) {
this.titlePanel.step = step;
this.attachTitleBarIfNeeded();
}

setTitle(title: string | undefined) {
this.titlePanel.title = title;
this.attachTitleBarIfNeeded();
}

setTotalSteps(totalSteps: number | undefined) {
this.titlePanel.totalSteps = totalSteps;
}

setButtons(buttons: ReadonlyArray<TitleButton>) {
this.titlePanel.buttons = buttons;
this.attachTitleBarIfNeeded();
}

get titlePanel(): InputTitleBar {
return this._titlePanel;
}

private removeTitleElement(): void {
if (this.titleElement) {
this.titleElement.remove();
}
}

private attachTitleBarIfNeeded(): void {
this.removeTitleElement();
this.titlePanel.isAttached = false;
if (this.titlePanel.shouldShowTitleBar()) {
if (!this.quickOpenService.widgetNode.contains(this.titleBarContainer)) {
this.quickOpenService.widgetNode.prepend(this.titleBarContainer);
}
const currentTheme = this.themeService.getCurrentTheme();
this.titleElement = this.titlePanel.attachTitleBar(currentTheme.id);
this.titleBarContainer.appendChild(this.titleElement);
this.titlePanel.isAttached = true;
}
}

protected defaultPrompt = "Press 'Enter' to confirm your input or 'Escape' to cancel";
protected createPrompt(prompt?: string): string {
return prompt ? `${prompt} (${this.defaultPrompt})` : this.defaultPrompt;
Expand All @@ -112,4 +230,9 @@ export class QuickInputService {
return this.onDidAcceptEmitter.event;
}

readonly onDidHideEmitter: Emitter<void> = new Emitter();
get onDidHide(): Event<void> {
return this.onDidHideEmitter.event;
}

}
Loading

0 comments on commit 3c29097

Please sign in to comment.