-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds a new template `Tree Editor` to the generator which allows to generate an extension with a tree master detail editor. Additionally, add a new menu Tree Editor with an entry to generate an example file to open in the editor. The tree editor uses a coffee machine example model. Co-authored-by: Florian Gareis <[email protected]> Co-authored-by: Jonas Helming <[email protected]> Signed-off-by: Lucas Koehler <[email protected]>
- Loading branch information
1 parent
05ead39
commit 7f2af8c
Showing
16 changed files
with
1,130 additions
and
3 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
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,10 @@ | ||
# Example tree editor | ||
|
||
The example extension demonstrates how to build tree editors in Eclipse Theia, which show the content of JSON files. | ||
|
||
## How to use the example tree editor | ||
|
||
In the running application, open the menu "Tree Editor"=>"New Example File". | ||
The created `.tree` file will automatically be opened with the example tree editor. | ||
The left side of the editor shows the hierarchy of the JSON data allowing you to create new children and delete nodes. | ||
The right site shows the properties of a selected node and allows the modification of the same. |
102 changes: 102 additions & 0 deletions
102
templates/tree-editor/example-file/example-file-command.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,102 @@ | ||
import { SingleTextInputDialog } from '@theia/core/lib/browser/dialogs'; | ||
import { ILogger } from '@theia/core/lib/common'; | ||
import { BinaryBuffer } from '@theia/core/lib/common/buffer'; | ||
import { Command } from '@theia/core/lib/common/command'; | ||
import URI from '@theia/core/lib/common/uri'; | ||
import { SingleUriCommandHandler } from '@theia/core/lib/common/uri-command-handler'; | ||
import { FileService } from '@theia/filesystem/lib/browser/file-service'; | ||
import { FileSystemUtils } from '@theia/filesystem/lib/common'; | ||
import { inject, injectable } from 'inversify'; | ||
import { OpenerService } from '@theia/core/lib/browser'; | ||
|
||
export const NewTreeExampleFileCommand: Command = { | ||
id: '<%= params.extensionPath %>-tree.newExampleFile', | ||
label: 'New Tree Example File' | ||
}; | ||
|
||
@injectable() | ||
export class NewTreeExampleFileCommandHandler implements SingleUriCommandHandler { | ||
constructor( | ||
@inject(OpenerService) | ||
protected readonly openerService: OpenerService, | ||
@inject(FileService) | ||
protected readonly fileService: FileService, | ||
@inject(ILogger) | ||
protected readonly logger: ILogger, | ||
) { } | ||
|
||
async execute(uri: URI) { | ||
const stat = await this.fileService.resolve(uri); | ||
if (!stat) { | ||
this.logger.error(`[NewTreeExampleFileCommandHandler] Could not create file stat for uri`, uri); | ||
return; | ||
} | ||
|
||
const dir = stat.isDirectory ? stat : await this.fileService.resolve(uri.parent); | ||
if (!dir) { | ||
this.logger.error(`[NewTreeExampleFileCommandHandler] Could not create file stat for uri`, uri.parent); | ||
return; | ||
} | ||
|
||
const dirUri = dir.resource; | ||
const preliminaryFileUri = FileSystemUtils.generateUniqueResourceURI(dirUri, dir, 'tree-example', '.tree'); | ||
const dialog = new SingleTextInputDialog({ | ||
title: 'New Example File', | ||
initialValue: preliminaryFileUri.path.base | ||
}); | ||
|
||
const fileName = await dialog.open(); | ||
if (fileName) { | ||
const fileUri = dirUri.resolve(fileName); | ||
const contentBuffer = BinaryBuffer.fromString(JSON.stringify(defaultData, null, 2)); | ||
this.fileService.createFile(fileUri, contentBuffer) | ||
.then(_ => this.openerService.getOpener(fileUri)) | ||
.then(openHandler => openHandler.open(fileUri)); | ||
} | ||
} | ||
} | ||
|
||
const defaultData = { | ||
"typeId": "Machine", | ||
"name": "Super Coffee 4000", | ||
"children": [ | ||
{ | ||
"typeId": "ControlUnit", | ||
"processor": { | ||
"socketconnectorType": "A1T", | ||
"manufactoringProcess": "18nm", | ||
"thermalDesignPower": 10, | ||
"numberOfCores": 2, | ||
"clockSpeed": 800, | ||
"vendor": "CMD", | ||
"advancedConfiguration": true | ||
}, | ||
"display": { | ||
"width": 70, | ||
"height": 40 | ||
}, | ||
"dimension": { | ||
"width": 100, | ||
"height": 80, | ||
"length": 50 | ||
}, | ||
"userDescription": "Small processing unit for user input" | ||
}, | ||
{ | ||
"typeId": "MultiComponent", | ||
"width": 100, | ||
"height": 100, | ||
"length": 60, | ||
"children": [ | ||
{ | ||
"typeId":"WaterTank", | ||
"capacity":400 | ||
}, | ||
{ | ||
"typeId":"DripTray", | ||
"material":"aluminium" | ||
} | ||
] | ||
} | ||
] | ||
} |
43 changes: 43 additions & 0 deletions
43
templates/tree-editor/example-file/example-file-contribution.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,43 @@ | ||
import { CommandContribution, CommandRegistry, MenuContribution, MenuModelRegistry, SelectionService, MAIN_MENU_BAR } from '@theia/core/lib/common'; | ||
import { inject, injectable } from 'inversify'; | ||
import { WorkspaceRootUriAwareCommandHandler } from '@theia/workspace/lib/browser/workspace-commands'; | ||
import { WorkspaceService } from '@theia/workspace/lib/browser'; | ||
import { NewTreeExampleFileCommandHandler, NewTreeExampleFileCommand } from './example-file-command'; | ||
|
||
const TREE_EDITOR_MAIN_MENU = [...MAIN_MENU_BAR, '9_treeeditormenu']; | ||
|
||
@injectable() | ||
export class NewTreeExampleFileCommandContribution implements CommandContribution { | ||
|
||
constructor( | ||
@inject(SelectionService) | ||
private readonly selectionService: SelectionService, | ||
@inject(WorkspaceService) | ||
private readonly workspaceService: WorkspaceService, | ||
@inject(NewTreeExampleFileCommandHandler) | ||
private readonly newExampleFileHandler: NewTreeExampleFileCommandHandler | ||
) { } | ||
|
||
registerCommands(registry: CommandRegistry): void { | ||
registry.registerCommand(NewTreeExampleFileCommand, | ||
new WorkspaceRootUriAwareCommandHandler( | ||
this.workspaceService, | ||
this.selectionService, | ||
this.newExampleFileHandler | ||
) | ||
); | ||
} | ||
} | ||
|
||
@injectable() | ||
export class NewTreeExampleFileMenuContribution implements MenuContribution { | ||
|
||
registerMenus(menus: MenuModelRegistry): void { | ||
menus.registerSubmenu(TREE_EDITOR_MAIN_MENU, 'Tree Editor'); | ||
|
||
menus.registerMenuAction(TREE_EDITOR_MAIN_MENU, { | ||
commandId: NewTreeExampleFileCommand.id, | ||
label: 'New Example File' | ||
}); | ||
} | ||
} |
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,8 @@ | ||
.theia-tree-editor-form { | ||
display: flex; | ||
} | ||
|
||
.theia-tree-editor-form > .jsonforms-container { | ||
flex-grow: 1; | ||
max-width: 960px; /* Half the width of a full hd display. */ | ||
} |
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,60 @@ | ||
import { CommandRegistry, MenuModelRegistry } from '@theia/core'; | ||
import { ApplicationShell, NavigatableWidgetOptions, OpenerService, WidgetOpenerOptions } from '@theia/core/lib/browser'; | ||
import URI from '@theia/core/lib/common/uri'; | ||
import { inject, injectable } from 'inversify'; | ||
import { | ||
BaseTreeEditorContribution, | ||
MasterTreeWidget, | ||
TreeEditor, | ||
} from '@eclipse-emfcloud/theia-tree-editor'; | ||
|
||
import { TreeModelService } from './tree/tree-model-service'; | ||
import { TreeEditorWidget } from './tree/tree-editor-widget'; | ||
import { TreeLabelProvider } from './tree/tree-label-provider'; | ||
|
||
@injectable() | ||
export class TreeContribution extends BaseTreeEditorContribution { | ||
@inject(ApplicationShell) protected shell: ApplicationShell; | ||
@inject(OpenerService) protected opener: OpenerService; | ||
|
||
constructor( | ||
@inject(TreeModelService) modelService: TreeEditor.ModelService, | ||
@inject(TreeLabelProvider) labelProvider: TreeLabelProvider | ||
) { | ||
super(TreeEditorWidget.WIDGET_ID, modelService, labelProvider); | ||
} | ||
|
||
readonly id = TreeEditorWidget.WIDGET_ID; | ||
readonly label = MasterTreeWidget.WIDGET_LABEL; | ||
|
||
canHandle(uri: URI): number { | ||
if (uri.path.ext === '.tree') { | ||
return 1000; | ||
} | ||
return 0; | ||
} | ||
|
||
registerCommands(commands: CommandRegistry): void { | ||
// register your custom commands here | ||
|
||
super.registerCommands(commands); | ||
} | ||
|
||
registerMenus(menus: MenuModelRegistry): void { | ||
// register your custom menu actions here | ||
|
||
super.registerMenus(menus); | ||
} | ||
|
||
protected createWidgetOptions(uri: URI, options?: WidgetOpenerOptions): NavigatableWidgetOptions { | ||
return { | ||
kind: 'navigatable', | ||
uri: this.serializeUri(uri) | ||
}; | ||
} | ||
|
||
protected serializeUri(uri: URI): string { | ||
return uri.withoutFragment().toString(); | ||
} | ||
|
||
} |
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,55 @@ | ||
import '@eclipse-emfcloud/theia-tree-editor/style/index.css'; | ||
import '@eclipse-emfcloud/theia-tree-editor/style/forms.css'; | ||
import '../../src/browser/style/editor.css'; | ||
|
||
import { CommandContribution, MenuContribution } from '@theia/core'; | ||
import { LabelProviderContribution, NavigatableWidgetOptions, OpenHandler, WidgetFactory } from '@theia/core/lib/browser'; | ||
import URI from '@theia/core/lib/common/uri'; | ||
import { ContainerModule } from 'inversify'; | ||
import { createBasicTreeContainter, NavigatableTreeEditorOptions } from '@eclipse-emfcloud/theia-tree-editor'; | ||
|
||
import { TreeContribution } from './tree-contribution'; | ||
import { TreeModelService } from './tree/tree-model-service'; | ||
import { TreeNodeFactory } from './tree/tree-node-factory'; | ||
import { TreeEditorWidget } from './tree/tree-editor-widget'; | ||
import { TreeLabelProvider } from './tree/tree-label-provider'; | ||
import { TreeLabelProviderContribution } from './tree-label-provider-contribution'; | ||
import { NewTreeExampleFileCommandHandler } from './example-file/example-file-command'; | ||
import { NewTreeExampleFileCommandContribution, NewTreeExampleFileMenuContribution } from './example-file/example-file-contribution'; | ||
|
||
export default new ContainerModule(bind => { | ||
// Bind Theia IDE contributions for the example file creation menu entry. | ||
bind(NewTreeExampleFileCommandHandler).toSelf(); | ||
bind(CommandContribution).to(NewTreeExampleFileCommandContribution); | ||
bind(MenuContribution).to(NewTreeExampleFileMenuContribution) | ||
|
||
// Bind Theia IDE contributions for the tree editor. | ||
bind(LabelProviderContribution).to(TreeLabelProviderContribution); | ||
bind(OpenHandler).to(TreeContribution); | ||
bind(MenuContribution).to(TreeContribution); | ||
bind(CommandContribution).to(TreeContribution); | ||
bind(LabelProviderContribution).to(TreeLabelProvider); | ||
|
||
// bind services to themselves because we use them outside of the editor widget, too. | ||
bind(TreeModelService).toSelf().inSingletonScope(); | ||
bind(TreeLabelProvider).toSelf().inSingletonScope(); | ||
|
||
bind<WidgetFactory>(WidgetFactory).toDynamicValue(context => ({ | ||
id: TreeEditorWidget.WIDGET_ID, | ||
createWidget: (options: NavigatableWidgetOptions) => { | ||
|
||
const treeContainer = createBasicTreeContainter( | ||
context.container, | ||
TreeEditorWidget, | ||
TreeModelService, | ||
TreeNodeFactory | ||
); | ||
|
||
// Bind options. | ||
const uri = new URI(options.uri); | ||
treeContainer.bind(NavigatableTreeEditorOptions).toConstantValue({ uri }); | ||
|
||
return treeContainer.get(TreeEditorWidget); | ||
} | ||
})); | ||
}); |
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,26 @@ | ||
import { LabelProviderContribution } from '@theia/core/lib/browser'; | ||
import URI from '@theia/core/lib/common/uri'; | ||
import { FileStat } from '@theia/filesystem/lib/common'; | ||
import { injectable } from 'inversify'; | ||
|
||
@injectable() | ||
export class TreeLabelProviderContribution implements LabelProviderContribution { | ||
canHandle(uri: object): number { | ||
let toCheck = uri; | ||
if (FileStat.is(toCheck)) { | ||
toCheck = new URI(toCheck.uri); | ||
} | ||
if (toCheck instanceof URI) { | ||
if (toCheck.path.ext === '.tree') { | ||
return 1000; | ||
} | ||
} | ||
return 0; | ||
} | ||
|
||
getIcon(): string { | ||
return 'fa fa-coffee dark-purple'; | ||
} | ||
|
||
// We don't need to specify getName() nor getLongName() because the default uri label provider is responsible for them. | ||
} |
Oops, something went wrong.