fix: the focus in the sketchbook widget

Ref: arduino/arduino-ide#1720

Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
This commit is contained in:
Akos Kitta 2023-03-24 10:42:17 +01:00 committed by Akos Kitta
parent 6e72be1b4c
commit eb1f247296
4 changed files with 47 additions and 22 deletions

View File

@ -20,6 +20,7 @@ import { Installable } from '../../common/protocol';
import { ListItemRenderer } from '../widgets/component-list/list-item-renderer'; import { ListItemRenderer } from '../widgets/component-list/list-item-renderer';
import { nls } from '@theia/core/lib/common'; import { nls } from '@theia/core/lib/common';
import { LibraryFilterRenderer } from '../widgets/component-list/filter-renderer'; import { LibraryFilterRenderer } from '../widgets/component-list/filter-renderer';
import { findChildTheiaButton } from '../utils/dom';
@injectable() @injectable()
export class LibraryListWidget extends ListWidget< export class LibraryListWidget extends ListWidget<
@ -243,17 +244,7 @@ class MessageBoxDialog extends AbstractDialog<MessageBoxDialog.Result> {
protected override onAfterAttach(message: Message): void { protected override onAfterAttach(message: Message): void {
super.onAfterAttach(message); super.onAfterAttach(message);
let buttonToFocus: HTMLButtonElement | undefined = undefined; findChildTheiaButton(this.controlPanel)?.focus();
for (const child of Array.from(this.controlPanel.children)) {
if (child instanceof HTMLButtonElement) {
if (child.classList.contains('main')) {
buttonToFocus = child;
break;
}
buttonToFocus = child;
}
}
buttonToFocus?.focus();
} }
} }
export namespace MessageBoxDialog { export namespace MessageBoxDialog {

View File

@ -0,0 +1,37 @@
import { notEmpty } from '@theia/core';
/**
* Finds the closest child HTMLButtonElement representing a Theia button.
* A button is a Theia button if it's a `<button>` element and has the `"theia-button"` class.
* If an element has multiple Theia button children, this function prefers `"main"` over `"secondary"` button.
*/
export function findChildTheiaButton(
element: HTMLElement,
recursive = false
): HTMLButtonElement | undefined {
let button: HTMLButtonElement | undefined = undefined;
const children = Array.from(element.children);
for (const child of children) {
if (
child instanceof HTMLButtonElement &&
child.classList.contains('theia-button')
) {
if (child.classList.contains('main')) {
return child;
}
button = child;
}
}
if (!button && recursive) {
button = children
.filter(isHTMLElement)
.map((childElement) => findChildTheiaButton(childElement, true))
.filter(notEmpty)
.shift();
}
return button;
}
function isHTMLElement(element: Element): element is HTMLElement {
return element instanceof HTMLElement;
}

View File

@ -9,6 +9,7 @@ import { BaseWidget } from '@theia/core/lib/browser/widgets/widget';
import { CommandService } from '@theia/core/lib/common/command'; import { CommandService } from '@theia/core/lib/common/command';
import { SketchbookTreeWidget } from './sketchbook-tree-widget'; import { SketchbookTreeWidget } from './sketchbook-tree-widget';
import { CreateNew } from '../sketchbook/create-new'; import { CreateNew } from '../sketchbook/create-new';
import { findChildTheiaButton } from '../../utils/dom';
@injectable() @injectable()
export abstract class BaseSketchbookCompositeWidget< export abstract class BaseSketchbookCompositeWidget<
@ -18,16 +19,17 @@ export abstract class BaseSketchbookCompositeWidget<
protected readonly commandService: CommandService; protected readonly commandService: CommandService;
private readonly compositeNode: HTMLElement; private readonly compositeNode: HTMLElement;
private readonly footerNode: HTMLElement;
private readonly footerRoot: Root; private readonly footerRoot: Root;
constructor() { constructor() {
super(); super();
this.compositeNode = document.createElement('div'); this.compositeNode = document.createElement('div');
this.compositeNode.classList.add('composite-node'); this.compositeNode.classList.add('composite-node');
const footerNode = document.createElement('div'); this.footerNode = document.createElement('div');
footerNode.classList.add('footer-node'); this.footerNode.classList.add('footer-node');
this.compositeNode.appendChild(footerNode); this.compositeNode.appendChild(this.footerNode);
this.footerRoot = createRoot(footerNode); this.footerRoot = createRoot(this.footerNode);
this.node.appendChild(this.compositeNode); this.node.appendChild(this.compositeNode);
this.title.closable = false; this.title.closable = false;
} }
@ -51,6 +53,7 @@ export abstract class BaseSketchbookCompositeWidget<
super.onActivateRequest(message); super.onActivateRequest(message);
// Sending a resize message is needed because otherwise the tree widget would render empty // Sending a resize message is needed because otherwise the tree widget would render empty
this.onResize(Widget.ResizeMessage.UnknownSize); this.onResize(Widget.ResizeMessage.UnknownSize);
findChildTheiaButton(this.footerNode, true)?.focus();
} }
protected override onResize(message: Widget.ResizeMessage): void { protected override onResize(message: Widget.ResizeMessage): void {

View File

@ -128,13 +128,7 @@ export class SketchbookWidget extends BaseWidget {
protected override onActivateRequest(message: Message): void { protected override onActivateRequest(message: Message): void {
super.onActivateRequest(message); super.onActivateRequest(message);
this.sketchbookCompositeWidget.activate();
// TODO: focus the active sketchbook
// if (this.editor) {
// this.editor.focus();
// } else {
// }
this.node.focus();
} }
protected override onResize(message: Widget.ResizeMessage): void { protected override onResize(message: Widget.ResizeMessage): void {