From bed3a7761eeadceb87be1df2aa7bb0959367a97f Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 14 Mar 2023 15:29:34 +0100 Subject: [PATCH] joh/fortunate rodent (#177091) * use actual height of widget * use more top padding for block decoration * move history into rhs toolbar, give up lhs toolbar --- .../interactive/browser/interactiveEditor.css | 9 +++-- .../browser/interactiveEditorActions.ts | 11 +++-- .../browser/interactiveEditorWidget.ts | 40 ++++++++++--------- .../interactive/common/interactiveEditor.ts | 4 +- 4 files changed, 34 insertions(+), 30 deletions(-) diff --git a/src/vs/editor/contrib/interactive/browser/interactiveEditor.css b/src/vs/editor/contrib/interactive/browser/interactiveEditor.css index ec47503dbd9..f62a55982f8 100644 --- a/src/vs/editor/contrib/interactive/browser/interactiveEditor.css +++ b/src/vs/editor/contrib/interactive/browser/interactiveEditor.css @@ -6,7 +6,7 @@ .monaco-editor .interactive-editor { z-index: 100; color: inherit; - padding: 6px 0 6px 6px; + padding: 6px 0 6px 3px; } /* body */ @@ -83,7 +83,6 @@ } .monaco-editor .interactive-editor .body .content .input .editor-container { - /* height: 24px; */ vertical-align: middle; } .monaco-editor .interactive-editor .body .toolbar { @@ -115,10 +114,14 @@ /* message */ .monaco-editor .interactive-editor .message { - padding: 6px 8px; + padding: 6px 0; color: var(--vscode-errorForeground); } +.monaco-editor .interactive-editor .message.hidden { + display: none; +} + /* decoration styles */ diff --git a/src/vs/editor/contrib/interactive/browser/interactiveEditorActions.ts b/src/vs/editor/contrib/interactive/browser/interactiveEditorActions.ts index f6f7fddc388..706618c3858 100644 --- a/src/vs/editor/contrib/interactive/browser/interactiveEditorActions.ts +++ b/src/vs/editor/contrib/interactive/browser/interactiveEditorActions.ts @@ -10,7 +10,7 @@ import { EditorAction2 } from 'vs/editor/browser/editorExtensions'; import { EmbeddedCodeEditorWidget } from 'vs/editor/browser/widget/embeddedCodeEditorWidget'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { InteractiveEditorController, Recording } from 'vs/editor/contrib/interactive/browser/interactiveEditorWidget'; -import { CTX_INTERACTIVE_EDITOR_FOCUSED, CTX_INTERACTIVE_EDITOR_HAS_ACTIVE_REQUEST, CTX_INTERACTIVE_EDITOR_HAS_PROVIDER, CTX_INTERACTIVE_EDITOR_INNER_CURSOR_FIRST, CTX_INTERACTIVE_EDITOR_INNER_CURSOR_LAST, CTX_INTERACTIVE_EDITOR_EMPTY, CTX_INTERACTIVE_EDITOR_OUTER_CURSOR_POSITION, CTX_INTERACTIVE_EDITOR_PREVIEW, CTX_INTERACTIVE_EDITOR_VISIBLE, MENU_INTERACTIVE_EDITOR_WIDGET, MENU_INTERACTIVE_EDITOR_WIDGET_LHS, CTX_INTERACTIVE_EDITOR_HISTORY_VISIBLE } from 'vs/editor/contrib/interactive/common/interactiveEditor'; +import { CTX_INTERACTIVE_EDITOR_FOCUSED, CTX_INTERACTIVE_EDITOR_HAS_ACTIVE_REQUEST, CTX_INTERACTIVE_EDITOR_HAS_PROVIDER, CTX_INTERACTIVE_EDITOR_INNER_CURSOR_FIRST, CTX_INTERACTIVE_EDITOR_INNER_CURSOR_LAST, CTX_INTERACTIVE_EDITOR_EMPTY, CTX_INTERACTIVE_EDITOR_OUTER_CURSOR_POSITION, CTX_INTERACTIVE_EDITOR_PREVIEW, CTX_INTERACTIVE_EDITOR_VISIBLE, MENU_INTERACTIVE_EDITOR_WIDGET, CTX_INTERACTIVE_EDITOR_HISTORY_VISIBLE, CTX_INTERACTIVE_EDITOR_HISTORY_POSSIBLE } from 'vs/editor/contrib/interactive/common/interactiveEditor'; import { localize } from 'vs/nls'; import { IAction2Options } from 'vs/platform/actions/common/actions'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; @@ -310,16 +310,15 @@ export class ToggleHistory extends AbstractInteractiveEditorAction { super({ id: 'interactiveEditor.toggleHistory', title: localize('toggleHistory', 'Toggle History'), - icon: Codicon.chevronRight, - precondition: CTX_INTERACTIVE_EDITOR_VISIBLE, + icon: Codicon.history, + precondition: ContextKeyExpr.and(CTX_INTERACTIVE_EDITOR_VISIBLE, CTX_INTERACTIVE_EDITOR_HISTORY_POSSIBLE), toggled: { condition: CTX_INTERACTIVE_EDITOR_HISTORY_VISIBLE, - icon: Codicon.chevronDown, }, menu: { - id: MENU_INTERACTIVE_EDITOR_WIDGET_LHS, + id: MENU_INTERACTIVE_EDITOR_WIDGET, group: 'main', - order: 1 + order: 2 } }); } diff --git a/src/vs/editor/contrib/interactive/browser/interactiveEditorWidget.ts b/src/vs/editor/contrib/interactive/browser/interactiveEditorWidget.ts index 88e0c219927..42a28482f74 100644 --- a/src/vs/editor/contrib/interactive/browser/interactiveEditorWidget.ts +++ b/src/vs/editor/contrib/interactive/browser/interactiveEditorWidget.ts @@ -15,7 +15,7 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/c import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ZoneWidget } from 'vs/editor/contrib/zoneWidget/browser/zoneWidget'; import { assertType } from 'vs/base/common/types'; -import { IInteractiveEditorResponse, IInteractiveEditorService, CTX_INTERACTIVE_EDITOR_FOCUSED, CTX_INTERACTIVE_EDITOR_HAS_ACTIVE_REQUEST, CTX_INTERACTIVE_EDITOR_INNER_CURSOR_FIRST, CTX_INTERACTIVE_EDITOR_INNER_CURSOR_LAST, CTX_INTERACTIVE_EDITOR_EMPTY, CTX_INTERACTIVE_EDITOR_OUTER_CURSOR_POSITION, CTX_INTERACTIVE_EDITOR_PREVIEW, CTX_INTERACTIVE_EDITOR_VISIBLE, MENU_INTERACTIVE_EDITOR_WIDGET, CTX_INTERACTIVE_EDITOR_HISTORY_VISIBLE, MENU_INTERACTIVE_EDITOR_WIDGET_LHS, IInteractiveEditorRequest, IInteractiveEditorSession } from 'vs/editor/contrib/interactive/common/interactiveEditor'; +import { IInteractiveEditorResponse, IInteractiveEditorService, CTX_INTERACTIVE_EDITOR_FOCUSED, CTX_INTERACTIVE_EDITOR_HAS_ACTIVE_REQUEST, CTX_INTERACTIVE_EDITOR_INNER_CURSOR_FIRST, CTX_INTERACTIVE_EDITOR_INNER_CURSOR_LAST, CTX_INTERACTIVE_EDITOR_EMPTY, CTX_INTERACTIVE_EDITOR_OUTER_CURSOR_POSITION, CTX_INTERACTIVE_EDITOR_PREVIEW, CTX_INTERACTIVE_EDITOR_VISIBLE, MENU_INTERACTIVE_EDITOR_WIDGET, CTX_INTERACTIVE_EDITOR_HISTORY_VISIBLE, IInteractiveEditorRequest, IInteractiveEditorSession, CTX_INTERACTIVE_EDITOR_HISTORY_POSSIBLE } from 'vs/editor/contrib/interactive/common/interactiveEditor'; import { EditOperation } from 'vs/editor/common/core/editOperation'; import { Iterable } from 'vs/base/common/iterator'; import { ICursorStateComputer, IModelDeltaDecoration, ITextModel, IValidEditOperation } from 'vs/editor/common/model'; @@ -65,7 +65,6 @@ class InteractiveEditorWidget { 'div.interactive-editor@root', [ h('div.body', [ - h('div.toolbar@lhsToolbar'), h('div.content', [ h('div.input@input', [ h('div.editor-placeholder@placeholder'), @@ -76,7 +75,7 @@ class InteractiveEditorWidget { h('div.toolbar@rhsToolbar'), ]), h('div.progress@progress'), - h('div.message@message'), + h('div.message.hidden@message'), ] ); @@ -86,6 +85,7 @@ class InteractiveEditorWidget { private readonly _inputEditor: ICodeEditor; private readonly _inputModel: ITextModel; private readonly _ctxInputEmpty: IContextKey; + private readonly _ctxHistoryPossible: IContextKey; private readonly _ctxHistoryVisible: IContextKey; private readonly _progressBar: ProgressBar; @@ -106,6 +106,7 @@ class InteractiveEditorWidget { @IInstantiationService private readonly _instantiationService: IInstantiationService, ) { + this._ctxHistoryPossible = CTX_INTERACTIVE_EDITOR_HISTORY_POSSIBLE.bindTo(this._contextKeyService); this._ctxHistoryVisible = CTX_INTERACTIVE_EDITOR_HISTORY_VISIBLE.bindTo(this._contextKeyService); // editor logic @@ -166,7 +167,6 @@ class InteractiveEditorWidget { this._inputModel = this._modelService.getModel(uri) ?? this._modelService.createModel('', null, uri); this._inputEditor.setModel(this._inputModel); - // show/hide placeholder depending on text model being empty // content height @@ -190,17 +190,12 @@ class InteractiveEditorWidget { this._store.add(addDisposableListener(this._elements.placeholder, 'click', () => this._inputEditor.focus())); - const lhsToolbar = this._instantiationService.createInstance(MenuWorkbenchToolBar, this._elements.lhsToolbar, MENU_INTERACTIVE_EDITOR_WIDGET_LHS, { - telemetrySource: 'interactiveEditorWidget-toolbar-lhs', - toolbarOptions: { primaryGroup: 'main' } - }); - this._store.add(lhsToolbar); - const rhsToolbar = this._instantiationService.createInstance(MenuWorkbenchToolBar, this._elements.rhsToolbar, MENU_INTERACTIVE_EDITOR_WIDGET, { - telemetrySource: 'interactiveEditorWidget-toolbar-rhs', + const toolbar = this._instantiationService.createInstance(MenuWorkbenchToolBar, this._elements.rhsToolbar, MENU_INTERACTIVE_EDITOR_WIDGET, { + telemetrySource: 'interactiveEditorWidget-toolbar', toolbarOptions: { primaryGroup: 'main' } }); - this._store.add(rhsToolbar); + this._store.add(toolbar); this._progressBar = new ProgressBar(this._elements.progress); this._store.add(this._progressBar); @@ -221,7 +216,7 @@ class InteractiveEditorWidget { const innerEditorWidth = Math.min( Number.MAX_SAFE_INTEGER, // TODO@jrieken define max width? - dim.width - (getTotalWidth(this._elements.lhsToolbar) + getTotalWidth(this._elements.rhsToolbar) + 12 /* L/R-padding */) + dim.width - (getTotalWidth(this._elements.rhsToolbar) + 12 /* L/R-padding */) ); const newDim = new Dimension(innerEditorWidth, this._inputEditor.getContentHeight()); if (!this._editorDim || !Dimension.equals(this._editorDim, newDim)) { @@ -233,7 +228,9 @@ class InteractiveEditorWidget { } getHeight(): number { - return this._inputEditor.getContentHeight() + getTotalHeight(this._elements.message) + getTotalHeight(this._elements.history); + const base = getTotalHeight(this._elements.progress) + getTotalHeight(this._elements.message) + getTotalHeight(this._elements.history); + const editorHeight = this._inputEditor.getContentHeight() + 6 /* padding and border */; + return base + editorHeight + 12 /* padding */; } updateProgress(show: boolean) { @@ -349,6 +346,8 @@ class InteractiveEditorWidget { this._onDidChangeHeight.fire(); } + this._ctxHistoryPossible.set(true); + return { updateVisibility: (visible) => { root.classList.toggle('hidden', !visible); @@ -372,16 +371,19 @@ class InteractiveEditorWidget { this._historyStore.clear(); this._isExpanded = false; this._elements.history.classList.toggle('hidden', true); + this._ctxHistoryPossible.reset(); this._ctxHistoryVisible.reset(); reset(this._elements.history); } showMessage(value: string) { + this._elements.message.classList.remove('hidden'); this._elements.message.innerText = value; this._onDidChangeHeight.fire(); } clearMessage() { + this._elements.message.classList.add('hidden'); reset(this._elements.message); this._onDidChangeHeight.fire(); } @@ -476,8 +478,7 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { private _computeHeightInLines(): number { const lineHeight = this.editor.getOption(EditorOption.lineHeight); - const contentHeightInLines = (this.widget.getHeight() / lineHeight); - return 2 + contentHeightInLines; + return this.widget.getHeight() / lineHeight; } protected override _relayout() { @@ -586,7 +587,7 @@ export class InteractiveEditorController implements IEditorContribution { description: 'interactive-editor', blockClassName: 'interactive-editor-block', blockDoesNotCollapse: true, - blockPadding: [1, 0, 1, 4] + blockPadding: [4, 0, 1, 4] }); private static _promptHistory: string[] = []; @@ -779,13 +780,14 @@ export class InteractiveEditorController implements IEditorContribution { this._logService.error('[IE] ERROR during request', provider.debugName); this._logService.error(e); this._zone.widget.showMessage(toErrorMessage(e)); + continue; } } finally { this._ctxHasActiveRequest.set(false); this._zone.widget.updateProgress(false); + this._logService.trace('[IE] request took', sw.elapsed(), provider.debugName); } - this._logService.trace('[IE] request took', sw.elapsed(), provider.debugName); if (this._ctsRequest.token.isCancellationRequested) { this._logService.trace('[IE] request CANCELED', provider.debugName); @@ -870,7 +872,7 @@ export class InteractiveEditorController implements IEditorContribution { InteractiveEditorController._promptHistory.unshift(input.value); } placeholder = reply.placeholder ?? session.placeholder ?? ''; - + value = ''; data.rounds += round + '|'; } while (!thisSession.token.isCancellationRequested); diff --git a/src/vs/editor/contrib/interactive/common/interactiveEditor.ts b/src/vs/editor/contrib/interactive/common/interactiveEditor.ts index 6e9d37edd6e..587ec2ea4bb 100644 --- a/src/vs/editor/contrib/interactive/common/interactiveEditor.ts +++ b/src/vs/editor/contrib/interactive/common/interactiveEditor.ts @@ -64,14 +64,14 @@ export interface IInteractiveEditorService { getAll(): Iterable; } -export const MENU_INTERACTIVE_EDITOR_WIDGET_LHS = MenuId.for('interactiveEditorWidgetLhs'); -export const MENU_INTERACTIVE_EDITOR_WIDGET = MenuId.for('interactiveEditorWidgetRhs'); +export const MENU_INTERACTIVE_EDITOR_WIDGET = MenuId.for('interactiveEditorWidget'); export const CTX_INTERACTIVE_EDITOR_HAS_PROVIDER = new RawContextKey('interactiveEditorHasProvider', false, localize('interactiveEditorHasProvider', "Whether a provider for interactive editors exists")); export const CTX_INTERACTIVE_EDITOR_VISIBLE = new RawContextKey('interactiveEditorVisible', false, localize('interactiveEditorVisible', "Whether the interactive editor input is visible")); export const CTX_INTERACTIVE_EDITOR_FOCUSED = new RawContextKey('interactiveEditorFocused', false, localize('interactiveEditorFocused', "Whether the interactive editor input is focused")); export const CTX_INTERACTIVE_EDITOR_EMPTY = new RawContextKey('interactiveEditorEmpty', false, localize('interactiveEditorEmpty', "Whether the interactive editor input is empty")); export const CTX_INTERACTIVE_EDITOR_PREVIEW = new RawContextKey('interactiveEditorPreview', false, localize('interactiveEditorPreview', "Whether the interactive editor input shows inline previews")); +export const CTX_INTERACTIVE_EDITOR_HISTORY_POSSIBLE = new RawContextKey('interactiveEditorHistoryPossible', false, localize('interactiveEditorHistoryPossible', "Whether the interactive editor has history entries")); export const CTX_INTERACTIVE_EDITOR_HISTORY_VISIBLE = new RawContextKey('interactiveEditorHistoryVisible', false, localize('interactiveEditorHistoryVisible', "Whether the interactive editor history is visible")); export const CTX_INTERACTIVE_EDITOR_INNER_CURSOR_FIRST = new RawContextKey('interactiveEditorInnerCursorFirst', false, localize('interactiveEditorInnerCursorFirst', "Whether the cursor of the iteractive editor input is on the first line")); export const CTX_INTERACTIVE_EDITOR_INNER_CURSOR_LAST = new RawContextKey('interactiveEditorInnerCursorLast', false, localize('interactiveEditorInnerCursorLast', "Whether the cursor of the iteractive editor input is on the last line"));