forked from arduino/arduino-ide
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ATL-988: Aligned the hover size to the expression.
Signed-off-by: Akos Kitta <kittaakos@typefox.io>
- Loading branch information
Showing
6 changed files
with
242 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/* TODO: remove after https://github.com/eclipse-theia/theia/pull/9256/ */ | ||
|
||
/* To fix colors in Theia. */ | ||
.theia-debug-hover-title.number, | ||
.theia-debug-console-variable.number { | ||
color: var(--theia-variable-number-variable-color); | ||
} | ||
.theia-debug-hover-title.boolean, | ||
.theia-debug-console-variable.boolean { | ||
color: var(--theia-variable-boolean-variable-color); | ||
} | ||
.theia-debug-hover-title.string, | ||
.theia-debug-console-variable.string { | ||
color: var(--theia-variable-string-variable-color); | ||
} | ||
|
||
/* To unset the default debug hover dimension. */ | ||
.theia-debug-hover { | ||
min-width: unset; | ||
min-height: unset; | ||
width: unset; | ||
height: unset; | ||
} | ||
|
||
/* To adjust the left padding in the hover title. */ | ||
.theia-debug-hover-title { | ||
padding-left: 5px; | ||
} | ||
|
||
/* Use the default Theia dimensions only iff the expression is complex (`!!expression.hasChildren~) */ | ||
.theia-debug-hover.complex-value { | ||
min-width: 324px; | ||
min-height: 324px; | ||
width: 324px; | ||
height: 324px; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
84 changes: 84 additions & 0 deletions
84
arduino-ide-extension/src/browser/theia/debug/debug-editor-model.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import debounce from 'p-debounce'; | ||
import { inject, injectable, postConstruct, interfaces, Container } from 'inversify'; | ||
import URI from '@theia/core/lib/common/uri'; | ||
import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable'; | ||
import { MonacoConfigurationService } from '@theia/monaco/lib/browser/monaco-frontend-module'; | ||
import { INLINE_VALUE_DECORATION_KEY } from '@theia/debug/lib/browser/editor//debug-inline-value-decorator'; | ||
import { DebugEditor } from '@theia/debug/lib/browser/editor/debug-editor'; | ||
import { DebugExceptionWidget } from '@theia/debug/lib/browser/editor/debug-exception-widget'; | ||
import { DebugBreakpointWidget } from '@theia/debug/lib/browser/editor/debug-breakpoint-widget'; | ||
import { DebugEditorModel as TheiaDebugEditorModel } from '@theia/debug/lib/browser/editor/debug-editor-model'; | ||
import { createDebugHoverWidgetContainer } from './debug-hover-widget' | ||
|
||
// TODO: Remove after https://github.com/eclipse-theia/theia/pull/9256/ | ||
@injectable() | ||
export class DebugEditorModel extends TheiaDebugEditorModel { | ||
|
||
static createContainer(parent: interfaces.Container, editor: DebugEditor): Container { | ||
const child = createDebugHoverWidgetContainer(parent, editor); | ||
child.bind(DebugEditorModel).toSelf(); | ||
child.bind(DebugBreakpointWidget).toSelf(); | ||
child.bind(DebugExceptionWidget).toSelf(); | ||
return child; | ||
} | ||
|
||
static createModel(parent: interfaces.Container, editor: DebugEditor): DebugEditorModel { | ||
return DebugEditorModel.createContainer(parent, editor).get(DebugEditorModel); | ||
} | ||
|
||
@inject(MonacoConfigurationService) | ||
readonly configurationService: monaco.services.IConfigurationService; | ||
|
||
protected readonly toDisposeOnRenderFrames = new DisposableCollection(); | ||
|
||
@postConstruct() | ||
protected init(): void { | ||
this.toDispose.push(this.toDisposeOnRenderFrames); | ||
super.init(); | ||
} | ||
|
||
protected async updateEditorHover(): Promise<void> { | ||
if (this.isCurrentEditorFrame(this.uri)) { | ||
const codeEditor = this.editor.getControl(); | ||
codeEditor.updateOptions({ hover: { enabled: false } }); | ||
this.toDisposeOnRenderFrames.push(Disposable.create(() => { | ||
const model = codeEditor.getModel()!; | ||
const overrides = { | ||
resource: model.uri, | ||
overrideIdentifier: (model as any).getLanguageIdentifier().language, | ||
}; | ||
const { enabled, delay, sticky } = this.configurationService._configuration.getValue('editor.hover', overrides, undefined); | ||
codeEditor.updateOptions({ | ||
hover: { | ||
enabled, | ||
delay, | ||
sticky | ||
} | ||
}); | ||
})); | ||
} | ||
} | ||
|
||
private isCurrentEditorFrame(uri: URI): boolean { | ||
return this.sessions.currentFrame?.source?.uri.toString() === uri.toString(); | ||
} | ||
|
||
protected readonly renderFrames = debounce(async () => { | ||
if (this.toDispose.disposed) { | ||
return; | ||
} | ||
this.toDisposeOnRenderFrames.dispose(); | ||
|
||
this.toggleExceptionWidget(); | ||
const [newFrameDecorations, inlineValueDecorations] = await Promise.all([ | ||
this.createFrameDecorations(), | ||
this.createInlineValueDecorations() | ||
]); | ||
const codeEditor = this.editor.getControl(); | ||
codeEditor.removeDecorations(INLINE_VALUE_DECORATION_KEY); | ||
codeEditor.setDecorations(INLINE_VALUE_DECORATION_KEY, inlineValueDecorations); | ||
this.frameDecorations = this.deltaDecorations(this.frameDecorations, newFrameDecorations); | ||
this.updateEditorHover(); | ||
}, 100); | ||
|
||
} |
18 changes: 18 additions & 0 deletions
18
arduino-ide-extension/src/browser/theia/debug/debug-hover-source.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { injectable } from 'inversify'; | ||
import { ExpressionItem, DebugVariable } from '@theia/debug/lib/browser/console/debug-console-items'; | ||
import { DebugHoverSource as TheiaDebugHoverSource } from '@theia/debug/lib/browser/editor/debug-hover-source'; | ||
|
||
// TODO: remove after https://github.com/eclipse-theia/theia/pull/9256/. | ||
@injectable() | ||
export class DebugHoverSource extends TheiaDebugHoverSource { | ||
|
||
async evaluate2(expression: string): Promise<ExpressionItem | DebugVariable | undefined> { | ||
const evaluated = await this.doEvaluate(expression); | ||
const elements = evaluated && await evaluated.getElements(); | ||
this._expression = evaluated; | ||
this.elements = elements ? [...elements] : []; | ||
this.fireDidChange(); | ||
return evaluated; | ||
} | ||
|
||
} |
96 changes: 96 additions & 0 deletions
96
arduino-ide-extension/src/browser/theia/debug/debug-hover-widget.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import { injectable, interfaces, Container } from 'inversify'; | ||
import { Widget } from '@phosphor/widgets'; | ||
import { SourceTreeWidget } from '@theia/core/lib/browser/source-tree'; | ||
import { DisposableCollection } from '@theia/core/lib/common/disposable'; | ||
import { DebugEditor } from '@theia/debug/lib/browser/editor/debug-editor'; | ||
import { DebugVariable } from '@theia/debug/lib/browser/console/debug-console-items'; | ||
import { DebugExpressionProvider } from '@theia/debug/lib/browser/editor/debug-expression-provider'; | ||
import { DebugHoverSource as TheiaDebugHoverSource } from '@theia/debug/lib/browser/editor/debug-hover-source'; | ||
import { DebugHoverWidget as TheiaDebugHoverWidget, ShowDebugHoverOptions } from '@theia/debug/lib/browser/editor/debug-hover-widget'; | ||
import { DebugHoverSource } from './debug-hover-source'; | ||
|
||
export function createDebugHoverWidgetContainer(parent: interfaces.Container, editor: DebugEditor): Container { | ||
const child = SourceTreeWidget.createContainer(parent, { | ||
virtualized: false | ||
}); | ||
child.bind(DebugEditor).toConstantValue(editor); | ||
child.bind(TheiaDebugHoverSource).toSelf(); | ||
child.bind(DebugHoverSource).toSelf(); | ||
child.rebind(TheiaDebugHoverSource).to(DebugHoverSource); | ||
child.unbind(SourceTreeWidget); | ||
child.bind(DebugExpressionProvider).toSelf(); | ||
child.bind(TheiaDebugHoverWidget).toSelf(); | ||
child.bind(DebugHoverWidget).toSelf(); | ||
child.rebind(TheiaDebugHoverWidget).to(DebugHoverWidget); | ||
return child; | ||
} | ||
|
||
// TODO: remove patch after https://github.com/eclipse-theia/theia/pull/9256/ | ||
@injectable() | ||
export class DebugHoverWidget extends TheiaDebugHoverWidget { | ||
|
||
protected async doShow(options: ShowDebugHoverOptions | undefined = this.options): Promise<void> { | ||
if (!this.isEditorFrame()) { | ||
this.hide(); | ||
return; | ||
} | ||
if (!options) { | ||
this.hide(); | ||
return; | ||
} | ||
if (this.options && this.options.selection.equalsRange(options.selection)) { | ||
return; | ||
} | ||
if (!this.isAttached) { | ||
Widget.attach(this, this.contentNode); | ||
} | ||
|
||
this.options = options; | ||
const matchingExpression = this.expressionProvider.get(this.editor.getControl().getModel()!, options.selection); | ||
if (!matchingExpression) { | ||
this.hide(); | ||
return; | ||
} | ||
const toFocus = new DisposableCollection(); | ||
if (this.options.focus === true) { | ||
toFocus.push(this.model.onNodeRefreshed(() => { | ||
toFocus.dispose(); | ||
this.activate(); | ||
})); | ||
} | ||
const expression = await (this.hoverSource as DebugHoverSource).evaluate2(matchingExpression); | ||
if (!expression || !expression.value) { | ||
toFocus.dispose(); | ||
this.hide(); | ||
return; | ||
} | ||
|
||
this.contentNode.hidden = false; | ||
['number', 'boolean', 'string'].forEach(token => this.titleNode.classList.remove(token)); | ||
this.domNode.classList.remove('complex-value'); | ||
if (expression.hasElements) { | ||
this.domNode.classList.add('complex-value'); | ||
} else { | ||
this.contentNode.hidden = true; | ||
if (expression.type === 'number' || expression.type === 'boolean' || expression.type === 'string') { | ||
this.titleNode.classList.add(expression.type); | ||
} else if (!isNaN(+expression.value)) { | ||
this.titleNode.classList.add('number'); | ||
} else if (DebugVariable.booleanRegex.test(expression.value)) { | ||
this.titleNode.classList.add('boolean'); | ||
} else if (DebugVariable.stringRegex.test(expression.value)) { | ||
this.titleNode.classList.add('string'); | ||
} | ||
} | ||
|
||
// super.show(); // Here we cannot call `super.show()` but have to call `show` on the `Widget` prototype. | ||
Widget.prototype.show.call(this); | ||
await new Promise<void>(resolve => { | ||
setTimeout(() => window.requestAnimationFrame(() => { | ||
this.editor.getControl().layoutContentWidget(this); | ||
resolve(); | ||
}), 0); | ||
}); | ||
} | ||
|
||
} |