Files
arduino-ide/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget.tsx
Akos Kitta c0488d1f64 fix: remote sketch creation if tree is not active
Closes #1715

Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
2022-11-29 11:19:13 +01:00

177 lines
5.3 KiB
TypeScript

import {
inject,
injectable,
postConstruct,
} from '@theia/core/shared/inversify';
import { toArray } from '@theia/core/shared/@phosphor/algorithm';
import { IDragEvent } from '@theia/core/shared/@phosphor/dragdrop';
import { DockPanel, Widget } from '@theia/core/shared/@phosphor/widgets';
import { Message, MessageLoop } from '@theia/core/shared/@phosphor/messaging';
import { Disposable } from '@theia/core/lib/common/disposable';
import { BaseWidget } from '@theia/core/lib/browser/widgets/widget';
import { SketchbookTreeWidget } from './sketchbook-tree-widget';
import { nls } from '@theia/core/lib/common';
import { URI } from '../../contributions/contribution';
import {
BaseSketchbookCompositeWidget,
SketchbookCompositeWidget,
} from './sketchbook-composite-widget';
@injectable()
export class SketchbookWidget extends BaseWidget {
static readonly LABEL = nls.localize(
'arduino/sketch/titleSketchbook',
'Sketchbook'
);
@inject(SketchbookCompositeWidget)
protected readonly sketchbookCompositeWidget: SketchbookCompositeWidget;
protected readonly sketchbookTreesContainer: DockPanel;
constructor() {
super();
this.id = 'arduino-sketchbook-widget';
this.title.caption = SketchbookWidget.LABEL;
this.title.label = SketchbookWidget.LABEL;
this.title.iconClass = 'fa fa-arduino-folder';
this.title.closable = true;
this.node.tabIndex = 0;
this.sketchbookTreesContainer = this.createTreesContainer();
}
@postConstruct()
protected init(): void {
this.sketchbookTreesContainer.addWidget(this.sketchbookCompositeWidget);
}
protected override onAfterAttach(message: Message): void {
super.onAfterAttach(message);
Widget.attach(this.sketchbookTreesContainer, this.node);
this.toDisposeOnDetach.push(
Disposable.create(() => Widget.detach(this.sketchbookTreesContainer))
);
}
/**
* The currently selected sketchbook tree widget inside the view.
*/
getTreeWidget(): SketchbookTreeWidget {
return this.sketchbookCompositeWidget.treeWidget;
}
/**
* An array of all sketchbook tree widgets managed by the view.
*/
getTreeWidgets(): SketchbookTreeWidget[] {
return toArray(this.sketchbookTreesContainer.widgets()).reduce(
(acc, curr) => {
if (curr instanceof BaseSketchbookCompositeWidget) {
acc.push(curr.treeWidget);
}
return acc;
},
[] as SketchbookTreeWidget[]
);
}
activeTreeWidgetId(): string | undefined {
const selectedTreeWidgets = toArray(
this.sketchbookTreesContainer.selectedWidgets()
).map(({ id }) => id);
if (selectedTreeWidgets.length > 1) {
console.warn(
`Found multiple selected tree widgets: ${JSON.stringify(
selectedTreeWidgets
)}. Expected only one.`
);
}
return selectedTreeWidgets.shift();
}
async revealSketchNode(treeWidgetId: string, nodeUri: string): Promise<void> {
const widget = toArray(this.sketchbookTreesContainer.widgets())
.filter(({ id }) => id === treeWidgetId)
.shift();
if (!widget) {
console.warn(`Could not find tree widget with ID: ${widget}`);
return;
}
// TODO: remove this when the remote/local sketchbooks and their widgets are cleaned up.
const findTreeWidget = (
widget: Widget | undefined
): SketchbookTreeWidget | undefined => {
if (widget instanceof SketchbookTreeWidget) {
return widget;
}
if (widget instanceof BaseSketchbookCompositeWidget) {
return widget.treeWidget;
}
return undefined;
};
const treeWidget = findTreeWidget(
toArray(this.sketchbookTreesContainer.widgets())
.filter(({ id }) => id === treeWidgetId)
.shift()
);
if (!treeWidget) {
console.warn(`Could not find tree widget with ID: ${treeWidget}`);
return;
}
this.sketchbookTreesContainer.activateWidget(widget);
const treeNode = await treeWidget.model.revealFile(new URI(nodeUri));
if (!treeNode) {
console.warn(`Could not find tree node with URI: ${nodeUri}`);
}
}
protected override onActivateRequest(message: Message): void {
super.onActivateRequest(message);
// TODO: focus the active sketchbook
// if (this.editor) {
// this.editor.focus();
// } else {
// }
this.node.focus();
}
protected override onResize(message: Widget.ResizeMessage): void {
super.onResize(message);
MessageLoop.sendMessage(
this.sketchbookTreesContainer,
Widget.ResizeMessage.UnknownSize
);
for (const widget of toArray(this.sketchbookTreesContainer.widgets())) {
MessageLoop.sendMessage(widget, Widget.ResizeMessage.UnknownSize);
}
}
protected override onAfterShow(msg: Message): void {
super.onAfterShow(msg);
this.onResize(Widget.ResizeMessage.UnknownSize);
}
protected createTreesContainer(): DockPanel {
const panel = new NoopDragOverDockPanel({
spacing: 0,
mode: 'single-document',
});
panel.addClass('sketchbook-trees-container');
panel.node.tabIndex = -1;
return panel;
}
}
export class NoopDragOverDockPanel extends DockPanel {
constructor(options?: DockPanel.IOptions) {
super(options);
NoopDragOverDockPanel.prototype['_evtDragOver'] = (event: IDragEvent) => {
event.preventDefault();
event.stopPropagation();
event.dropAction = 'none';
};
}
}