Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit e56f5cd

Browse files
committed
Sketchbook explorer
1 parent 0c5c736 commit e56f5cd

File tree

10 files changed

+280
-41
lines changed

10 files changed

+280
-41
lines changed

‎arduino-ide-extension/src/browser/data/arduino.color-theme.json‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,11 @@
8585
],
8686
"colors": {
8787
"list.highlightForeground": "#005c5f",
88-
"list.activeSelectionBackground": "#005c5f",
88+
"list.activeSelectionForeground": "#424242",
89+
"list.activeSelectionBackground": "#DAE3E3",
90+
"list.inactiveSelectionForeground": "#424242",
91+
"list.inactiveSelectionBackground": "#DAE3E3",
92+
"list.hoverBackground": "#ECF1F1",
8993
"progressBar.background": "#005c5f",
9094
"editor.background": "#ffffff",
9195
"editorCursor.foreground": "#434f54",

‎arduino-ide-extension/src/browser/settings.tsx‎

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export interface Settings extends Index {
3434
verboseOnUpload: boolean; // `arduino.upload.verbose`
3535
verifyAfterUpload: boolean; // `arduino.upload.verify`
3636
enableLsLogs: boolean; // `arduino.language.log`
37+
sketchbookShowAllFiles: boolean; // `arduino.sketchbook.showAllFiles`
3738

3839
sketchbookPath: string; // CLI
3940
additionalUrls: string[]; // CLI
@@ -94,7 +95,8 @@ export class SettingsService {
9495
verboseOnUpload,
9596
verifyAfterUpload,
9697
enableLsLogs,
97-
cliConfig
98+
sketchbookShowAllFiles,
99+
cliConfig,
98100
] = await Promise.all([
99101
this.preferenceService.get<number>('editor.fontSize', 12),
100102
this.preferenceService.get<string>('workbench.colorTheme', 'arduino-theme'),
@@ -112,6 +114,7 @@ export class SettingsService {
112114
this.preferenceService.get<boolean>('arduino.upload.verbose', true),
113115
this.preferenceService.get<boolean>('arduino.upload.verify', true),
114116
this.preferenceService.get<boolean>('arduino.language.log', true),
117+
this.preferenceService.get<boolean>('arduino.sketchbook.showAllFiles', false),
115118
this.configService.getConfiguration()
116119
]);
117120
const { additionalUrls, sketchDirUri, network } = cliConfig;
@@ -129,6 +132,7 @@ export class SettingsService {
129132
verboseOnUpload,
130133
verifyAfterUpload,
131134
enableLsLogs,
135+
sketchbookShowAllFiles,
132136
additionalUrls,
133137
sketchbookPath,
134138
network
@@ -194,7 +198,8 @@ export class SettingsService {
194198
enableLsLogs,
195199
sketchbookPath,
196200
additionalUrls,
197-
network
201+
network,
202+
sketchbookShowAllFiles
198203
} = this._settings;
199204
const [config, sketchDirUri] = await Promise.all([
200205
this.configService.getConfiguration(),
@@ -217,6 +222,7 @@ export class SettingsService {
217222
this.preferenceService.set('arduino.upload.verbose', verboseOnUpload, PreferenceScope.User),
218223
this.preferenceService.set('arduino.upload.verify', verifyAfterUpload, PreferenceScope.User),
219224
this.preferenceService.set('arduino.language.log', enableLsLogs, PreferenceScope.User),
225+
this.preferenceService.set('arduino.sketchbook.showAllFiles', sketchbookShowAllFiles, PreferenceScope.User),
220226
this.configService.setConfiguration(config)
221227
]);
222228
this.onDidChangeEmitter.fire(this._settings);
@@ -370,6 +376,13 @@ export class SettingsComponent extends React.Component<SettingsComponent.Props,
370376
onChange={this.autoSaveDidChange} />
371377
Auto save
372378
</label>
379+
<label className='flex-line'>
380+
<input
381+
type='checkbox'
382+
checked={this.state.sketchbookShowAllFiles === true}
383+
onChange={this.sketchbookShowAllFilesDidChange} />
384+
Sketchbook show files
385+
</label>
373386
<label className='flex-line'>
374387
<input
375388
type='checkbox'
@@ -564,6 +577,10 @@ export class SettingsComponent extends React.Component<SettingsComponent.Props,
564577
this.setState({ checkForUpdates: event.target.checked });
565578
};
566579

580+
protected sketchbookShowAllFilesDidChange = (event: React.ChangeEvent<HTMLInputElement>) => {
581+
this.setState({ sketchbookShowAllFiles: event.target.checked });
582+
};
583+
567584
protected autoSaveDidChange = (event: React.ChangeEvent<HTMLInputElement>) => {
568585
this.setState({ autoSave: event.target.checked ? 'on' : 'off' });
569586
};
Lines changed: 10 additions & 0 deletions
Loading[フレーム]

‎arduino-ide-extension/src/browser/style/sketchbook.css‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,13 @@
1818
.sketchbook-trees-container {
1919
height: 99%;
2020
}
21+
22+
.sketchbook-tree__opts {
23+
background: url('./sketchbook-opts-icon.svg') center center no-repeat;
24+
width: var(--theia-icon-size);
25+
height: var(--theia-icon-size);
26+
}
27+
28+
#arduino-sketchbook-tree-widget .theia-TreeNodeSegmentGrow {
29+
flex: 1;
30+
}

‎arduino-ide-extension/src/browser/theia/core/common-frontend-contribution.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ export class CommonFrontendContribution extends TheiaCommonFrontendContribution
2121
CommonCommands.SELECT_ICON_THEME,
2222
CommonCommands.SELECT_COLOR_THEME,
2323
CommonCommands.ABOUT_COMMAND,
24+
CommonCommands.CLOSE_TAB,
25+
CommonCommands.CLOSE_OTHER_TABS,
26+
CommonCommands.CLOSE_ALL_TABS,
27+
CommonCommands.COLLAPSE_PANEL,
2428
CommonCommands.SAVE_WITHOUT_FORMATTING // Patched for https://github.com/eclipse-theia/theia/pull/8877
2529
]) {
2630
registry.unregisterMenuAction(command);

‎arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-commands.ts‎

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,32 @@ import { Command } from '@theia/core/lib/common/command';
22

33
export namespace SketchbookCommands {
44

5-
export const OPEN: Command = {
6-
id: 'arduino-sketchbook--open-sketch',
7-
label: 'Open Sketch',
8-
iconClass: 'fa fa-play-circle'
9-
};
10-
115
export const OPEN_NEW_WINDOW: Command = {
126
id: 'arduino-sketchbook--open-sketch-new-window',
137
label: 'Open Sketch in New Window',
14-
iconClass: 'fa fa-check'
158
};
169

10+
export const REVEAL_IN_FINDER: Command = {
11+
id: 'arduino-sketchbook--reveal-in-finder',
12+
label: 'Open Folder',
13+
};
14+
15+
export const OPEN_SKETCHBOOK_CONTEXT_MENU: Command = {
16+
id: 'arduino-sketchbook--open-sketch-context-menu',
17+
label: 'Contextual menu',
18+
iconClass: 'sketchbook-tree__opts'
19+
};
20+
21+
export const SKETCHBOOK_HIDE_FILES: Command = {
22+
id: 'arduino-sketchbook--hide-files',
23+
label: 'Contextual menu',
24+
};
25+
26+
export const SKETCHBOOK_SHOW_FILES: Command = {
27+
id: 'arduino-sketchbook--show-files',
28+
label: 'Contextual menu',
29+
};
30+
31+
32+
1733
}

‎arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-tree-model.ts‎

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
import { inject, injectable } from 'inversify';
22
import URI from '@theia/core/lib/common/uri';
3-
import { FileTreeModel } from '@theia/filesystem/lib/browser';
3+
import { FileNode,FileTreeModel } from '@theia/filesystem/lib/browser';
44
import { FileService } from '@theia/filesystem/lib/browser/file-service';
55
import { ConfigService } from '../../../common/protocol';
66
import { SketchbookTree } from './sketchbook-tree';
77
import { ArduinoPreferences } from '../../arduino-preferences';
8+
import { SelectableTreeNode, TreeNode } from '@theia/core/lib/browser/tree';
9+
import { SketchbookCommands } from './sketchbook-commands';
10+
import { OpenerService, open } from '@theia/core/lib/browser';
11+
import { SketchesServiceClientImpl } from '../../../common/protocol/sketches-service-client-impl';
12+
import { CommandRegistry } from '@theia/core/lib/common/command';
813

914
@injectable()
1015
export class SketchbookTreeModel extends FileTreeModel {
@@ -15,14 +20,82 @@ export class SketchbookTreeModel extends FileTreeModel {
1520
@inject(ArduinoPreferences)
1621
protected readonly arduinoPreferences: ArduinoPreferences;
1722

23+
@inject(CommandRegistry)
24+
protected readonly commandRegistry: CommandRegistry;
25+
1826
@inject(ConfigService)
1927
protected readonly configService: ConfigService;
2028

29+
@inject(OpenerService)
30+
protected readonly openerService: OpenerService;
31+
32+
@inject(SketchesServiceClientImpl)
33+
protected readonly sketchServiceClient: SketchesServiceClientImpl;
34+
2135
async updateRoot(): Promise<void> {
2236
const config = await this.configService.getConfiguration();
2337
const fileStat = await this.fileService.resolve(new URI(config.sketchDirUri));
2438
const showAllFiles = this.arduinoPreferences['arduino.sketchbook.showAllFiles'];
2539
this.tree.root = SketchbookTree.RootNode.create(fileStat, showAllFiles);
2640
}
2741

42+
// selectNode gets called when the user single-clicks on an item
43+
// when this happens, we want to open the file if it belongs to the currently open sketch
44+
async selectNode(node: Readonly<SelectableTreeNode>): Promise<void> {
45+
46+
super.selectNode(node);
47+
if (FileNode.is(node)) {
48+
open(this.openerService, node.uri);
49+
}
50+
51+
}
52+
53+
protected async doOpenNode(node: TreeNode): Promise<void> {
54+
// if it's a sketch dir, or a file from another sketch, open in new window
55+
if (!(await this.isFileInsideCurrentSketch(node))) {
56+
const sketchRoot = this.recursivelyFindSketchRoot(node);
57+
if (sketchRoot) {
58+
this.commandRegistry.executeCommand(SketchbookCommands.OPEN_NEW_WINDOW.id, { node: sketchRoot })
59+
}
60+
return;
61+
}
62+
63+
if (node.visible === false) {
64+
return;
65+
} else if (FileNode.is(node)) {
66+
open(this.openerService, node.uri);
67+
} else {
68+
super.doOpenNode(node);
69+
}
70+
}
71+
72+
private async isFileInsideCurrentSketch(node: TreeNode): Promise<boolean> {
73+
74+
// it's a directory, not a file
75+
if (!FileNode.is(node)) {
76+
return false;
77+
}
78+
79+
// check if the node is a file that belongs to another sketch
80+
const sketch = await this.sketchServiceClient.currentSketch();
81+
if (sketch && node.uri.toString().indexOf(sketch.uri) !== 0) {
82+
return false;
83+
}
84+
return true;
85+
}
86+
87+
private recursivelyFindSketchRoot(node: TreeNode): TreeNode | false {
88+
89+
if (node && SketchbookTree.SketchDirNode.is(node)) {
90+
return node;
91+
}
92+
93+
if (node && node.parent) {
94+
return this.recursivelyFindSketchRoot(node.parent);
95+
}
96+
97+
// can't find a root, return false
98+
return false;
99+
}
100+
28101
}

‎arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-tree-widget.tsx‎

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import { ContextMenuRenderer } from '@theia/core/lib/browser/context-menu-render
99
import { SketchbookTree } from './sketchbook-tree';
1010
import { SketchbookTreeModel } from './sketchbook-tree-model';
1111
import { ArduinoPreferences } from '../../arduino-preferences';
12+
import { SketchesServiceClientImpl } from '../../../common/protocol/sketches-service-client-impl';
13+
import { SelectableTreeNode } from '@theia/core/lib/browser/tree/tree-selection';
1214

1315
@injectable()
1416
export class SketchbookTreeWidget extends FileTreeWidget {
@@ -19,6 +21,11 @@ export class SketchbookTreeWidget extends FileTreeWidget {
1921
@inject(ArduinoPreferences)
2022
protected readonly arduinoPreferences: ArduinoPreferences;
2123

24+
@inject(SketchesServiceClientImpl)
25+
protected readonly sketchServiceClient: SketchesServiceClientImpl;
26+
27+
private currentSketchUri = '';
28+
2229
constructor(
2330
@inject(TreeProps) readonly props: TreeProps,
2431
@inject(SketchbookTreeModel) readonly model: SketchbookTreeModel,
@@ -41,6 +48,9 @@ export class SketchbookTreeWidget extends FileTreeWidget {
4148
}
4249
}));
4350
this.updateModel();
51+
// cache the current open sketch uri
52+
const currentSketch = await this.sketchServiceClient.currentSketch();
53+
this.currentSketchUri = currentSketch && currentSketch.uri || '';
4454
}
4555

4656
async updateModel(): Promise<void> {
@@ -80,7 +90,7 @@ export class SketchbookTreeWidget extends FileTreeWidget {
8090
}
8191

8292
protected renderInlineCommands(node: TreeNode, props: NodeProps): React.ReactNode {
83-
if (SketchbookTree.SketchDirNode.is(node) && node.commands && node.id === this.hoveredNodeId) {
93+
if (SketchbookTree.SketchDirNode.is(node) && (node.commands && node.id === this.hoveredNodeId||this.currentSketchUri===node?.uri.toString())) {
8494
return Array.from(new Set(node.commands)).map(command => this.renderInlineCommand(command.id, node));
8595
}
8696
return undefined;
@@ -99,11 +109,48 @@ export class SketchbookTreeWidget extends FileTreeWidget {
99109
onClick={event => {
100110
event.preventDefault();
101111
event.stopPropagation();
102-
this.commandRegistry.executeCommand(commandId, Object.assign(args, { event: event.nativeEvent }))
112+
this.commandRegistry.executeCommand(commandId, Object.assign(args, { event: event.nativeEvent }));
103113
}}
104114
/>;
105115
}
106116
return undefined;
107117
}
108118

119+
protected handleClickEvent(node: TreeNode | undefined, event: React.MouseEvent<HTMLElement>): void {
120+
121+
if (node) {
122+
if (!!this.props.multiSelect) {
123+
const shiftMask = this.hasShiftMask(event);
124+
const ctrlCmdMask = this.hasCtrlCmdMask(event);
125+
if (SelectableTreeNode.is(node)) {
126+
if (shiftMask) {
127+
this.model.selectRange(node);
128+
} else if (ctrlCmdMask) {
129+
this.model.toggleNode(node);
130+
} else {
131+
this.model.selectNode(node);
132+
}
133+
}
134+
} else {
135+
if (SelectableTreeNode.is(node)) {
136+
this.model.selectNode(node);
137+
}
138+
}
139+
event.stopPropagation();
140+
}
141+
142+
}
143+
144+
protected doToggle(event: React.MouseEvent<HTMLElement>): void {
145+
146+
const nodeId = event.currentTarget.getAttribute('data-node-id');
147+
if (nodeId) {
148+
const node = this.model.getNode(nodeId);
149+
if (node && this.isExpandable(node)) {
150+
this.model.toggleNodeExpansion(node);
151+
}
152+
}
153+
event.stopPropagation();
154+
}
155+
109156
}

‎arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-tree.ts‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,13 @@ export class SketchbookTree extends FileTree {
2727
if (!SketchbookTree.RootNode.is(root)) {
2828
return [];
2929
}
30-
const children = await Promise.all((await super.resolveChildren(parent)).map(node => this.maybeDecorateNode(node, root.showAllFiles)));
30+
const children = (await Promise.all((await super.resolveChildren(parent)).map(node => this.maybeDecorateNode(node, root.showAllFiles)))).filter(node => {
31+
// filter out hidden nodes
32+
if (DirNode.is(node) || FileStatNode.is(node)) {
33+
return node.fileStat.name.indexOf('.') !== 0
34+
}
35+
return true;
36+
});
3137
if (SketchbookTree.RootNode.is(parent)) {
3238
return children.filter(DirNode.is).filter(node => ['libraries', 'hardware'].indexOf(this.labelProvider.getName(node)) === -1);
3339
}
@@ -41,7 +47,7 @@ export class SketchbookTree extends FileTree {
4147
if (DirNode.is(node)) {
4248
const sketch = await this.sketchesService.maybeLoadSketch(node.uri.toString());
4349
if (sketch) {
44-
Object.assign(node, { type: 'sketch', commands: [SketchbookCommands.OPEN,SketchbookCommands.OPEN_NEW_WINDOW] });
50+
Object.assign(node, { type: 'sketch', commands: [SketchbookCommands.OPEN_SKETCHBOOK_CONTEXT_MENU] });
4551
if (!showAllFiles) {
4652
delete (node as any).expanded;
4753
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /