@@ -4,7 +4,6 @@ import URI from '@theia/core/lib/common/uri';
4
4
import { EditorWidget } from '@theia/editor/lib/browser/editor-widget' ;
5
5
import { MessageService } from '@theia/core/lib/common/message-service' ;
6
6
import { CommandContribution , CommandRegistry } from '@theia/core/lib/common/command' ;
7
- import { DefaultFrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application' ;
8
7
import { TabBarToolbarContribution , TabBarToolbarRegistry } from '@theia/core/lib/browser/shell/tab-bar-toolbar' ;
9
8
import { BoardsService } from '../common/protocol/boards-service' ;
10
9
import { ArduinoCommands } from './arduino-commands' ;
@@ -15,15 +14,22 @@ import { ToolOutputServiceClient } from '../common/protocol/tool-output-service'
15
14
import { QuickPickService } from '@theia/core/lib/common/quick-pick-service' ;
16
15
import { BoardsListWidgetFrontendContribution } from './boards/boards-widget-frontend-contribution' ;
17
16
import { BoardsNotificationService } from './boards-notification-service' ;
18
- import { WorkspaceRootUriAwareCommandHandler } from '@theia/workspace/lib/browser/workspace-commands' ;
17
+ import { WorkspaceRootUriAwareCommandHandler , WorkspaceCommands } from '@theia/workspace/lib/browser/workspace-commands' ;
19
18
import { SelectionService } from '@theia/core' ;
20
19
import { WorkspaceService } from '@theia/workspace/lib/browser/workspace-service' ;
21
20
import { SketchFactory } from './sketch-factory' ;
22
21
import { ArduinoToolbar } from './toolbar/arduino-toolbar' ;
23
22
import { EditorManager } from '@theia/editor/lib/browser' ;
23
+ import { ContextMenuRenderer , OpenerService , Widget } from '@theia/core/lib/browser' ;
24
+ import { OpenFileDialogProps , FileDialogService } from '@theia/filesystem/lib/browser/file-dialog' ;
25
+ import { FileSystem } from '@theia/filesystem/lib/common' ;
26
+ import { ArduinoOpenSketchContextMenu } from './arduino-file-menu' ;
27
+ import { Sketch , SketchesService } from '../common/protocol/sketches-service' ;
28
+ import { WindowService } from '@theia/core/lib/browser/window/window-service' ;
29
+ import { CommonCommands } from '@theia/core/lib/browser/common-frontend-contribution'
24
30
25
31
@injectable ( )
26
- export class ArduinoFrontendContribution extends DefaultFrontendApplicationContribution implements TabBarToolbarContribution , CommandContribution {
32
+ export class ArduinoFrontendContribution implements TabBarToolbarContribution , CommandContribution {
27
33
28
34
@inject ( MessageService )
29
35
protected readonly messageService : MessageService ;
@@ -61,6 +67,24 @@ export class ArduinoFrontendContribution extends DefaultFrontendApplicationContr
61
67
@inject ( EditorManager )
62
68
protected readonly editorManager : EditorManager ;
63
69
70
+ @inject ( ContextMenuRenderer )
71
+ protected readonly contextMenuRenderer : ContextMenuRenderer ;
72
+
73
+ @inject ( FileDialogService )
74
+ protected readonly fileDialogService : FileDialogService ;
75
+
76
+ @inject ( FileSystem )
77
+ protected readonly fileSystem : FileSystem ;
78
+
79
+ @inject ( OpenerService )
80
+ protected readonly openerService : OpenerService ;
81
+
82
+ @inject ( WindowService )
83
+ protected readonly windowService : WindowService ;
84
+
85
+ @inject ( SketchesService )
86
+ protected readonly sketches : SketchesService ;
87
+
64
88
@postConstruct ( )
65
89
protected async init ( ) : Promise < void > {
66
90
// This is a hack. Otherwise, the backend services won't bind.
@@ -72,18 +96,31 @@ export class ArduinoFrontendContribution extends DefaultFrontendApplicationContr
72
96
id : ArduinoCommands . VERIFY . id ,
73
97
command : ArduinoCommands . VERIFY . id ,
74
98
tooltip : 'Verify' ,
75
- group : 'arduino' ,
76
99
text : '$(check)'
77
100
} ) ;
78
101
registry . registerItem ( {
79
102
id : ArduinoCommands . UPLOAD . id ,
80
103
command : ArduinoCommands . UPLOAD . id ,
81
104
tooltip : 'Upload' ,
82
- group : 'arduino' ,
83
105
text : '$(arrow-right)'
84
106
} ) ;
107
+ registry . registerItem ( {
108
+ id : ArduinoCommands . SHOW_OPEN_CONTEXT_MENU . id ,
109
+ command : ArduinoCommands . SHOW_OPEN_CONTEXT_MENU . id ,
110
+ tooltip : 'Open' ,
111
+ text : '$(arrow-up)'
112
+ } ) ;
113
+ registry . registerItem ( {
114
+ id : ArduinoCommands . SAVE_SKETCH . id ,
115
+ command : ArduinoCommands . SAVE_SKETCH . id ,
116
+ tooltip : 'Save' ,
117
+ text : '$(arrow-down)'
118
+ } ) ;
85
119
registry . registerItem ( {
86
120
id : ConnectedBoards . TOOLBAR_ID ,
121
+ // render: () => <BoardsToolBarItem
122
+ // onNoBoardsInstalled={this.onNoBoardsInstalled.bind(this)}
123
+ // onUnknownBoard={this.onUnknownBoard.bind(this)} />,
87
124
render : ( ) => < ConnectedBoards
88
125
boardsService = { this . boardService }
89
126
boardsNotificationService = { this . boardsNotificationService }
@@ -137,6 +174,36 @@ export class ArduinoFrontendContribution extends DefaultFrontendApplicationContr
137
174
}
138
175
}
139
176
} ) ;
177
+ registry . registerCommand ( ArduinoCommands . SHOW_OPEN_CONTEXT_MENU , {
178
+ isVisible : widget => this . isArduinoToolbar ( widget ) ,
179
+ isEnabled : widget => this . isArduinoToolbar ( widget ) ,
180
+ execute : async ( widget : Widget , event : React . MouseEvent < HTMLElement > ) => {
181
+ const el = ( event . target as HTMLElement ) . parentElement ;
182
+ if ( el ) {
183
+ this . contextMenuRenderer . render ( ArduinoOpenSketchContextMenu . PATH , {
184
+ x : el . getBoundingClientRect ( ) . left ,
185
+ y : el . getBoundingClientRect ( ) . top + el . offsetHeight
186
+ } ) ;
187
+ }
188
+ }
189
+ } ) ;
190
+ registry . registerCommand ( ArduinoCommands . OPEN_FILE_NAVIGATOR , {
191
+ isEnabled : ( ) => true ,
192
+ execute : ( ) => this . doOpenFile ( )
193
+ } )
194
+ registry . registerCommand ( ArduinoCommands . OPEN_SKETCH , {
195
+ isEnabled : ( ) => true ,
196
+ execute : async ( sketch : Sketch ) => {
197
+ this . openSketchFilesInNewWindow ( sketch . uri ) ;
198
+ }
199
+ } )
200
+ registry . registerCommand ( ArduinoCommands . SAVE_SKETCH , {
201
+ isEnabled : widget => this . isArduinoToolbar ( widget ) ,
202
+ isVisible : widget => this . isArduinoToolbar ( widget ) ,
203
+ execute : async ( sketch : Sketch ) => {
204
+ registry . executeCommand ( CommonCommands . SAVE_ALL . id ) ;
205
+ }
206
+ } )
140
207
registry . registerCommand ( ArduinoCommands . NEW_SKETCH , new WorkspaceRootUriAwareCommandHandler ( this . workspaceService , this . selectionService , {
141
208
execute : async uri => {
142
209
try {
@@ -157,6 +224,49 @@ export class ArduinoFrontendContribution extends DefaultFrontendApplicationContr
157
224
} )
158
225
}
159
226
227
+ protected async openSketchFilesInNewWindow ( uri : string ) {
228
+ const location = new URL ( window . location . href ) ;
229
+ location . searchParams . set ( 'sketch' , uri ) ;
230
+ this . windowService . openNewWindow ( location . toString ( ) ) ;
231
+ }
232
+
233
+ async openSketchFiles ( uri : string ) {
234
+ const fileStat = await this . fileSystem . getFileStat ( uri ) ;
235
+ if ( fileStat ) {
236
+ const sketchFiles = await this . sketches . getSketchFiles ( fileStat ) ;
237
+ sketchFiles . forEach ( sketchFile => {
238
+ const uri = new URI ( sketchFile ) ;
239
+ this . editorManager . open ( uri ) ;
240
+ } ) ;
241
+ }
242
+ }
243
+
244
+ /**
245
+ * Opens a file after prompting the `Open File` dialog. Resolves to `undefined`, if
246
+ * - the workspace root is not set,
247
+ * - the file to open does not exist, or
248
+ * - it was not a file, but a directory.
249
+ *
250
+ * Otherwise, resolves to the URI of the file.
251
+ */
252
+ protected async doOpenFile ( ) : Promise < URI | undefined > {
253
+ const props : OpenFileDialogProps = {
254
+ title : WorkspaceCommands . OPEN_FILE . dialogLabel ,
255
+ canSelectFolders : false ,
256
+ canSelectFiles : true
257
+ } ;
258
+ const [ rootStat ] = await this . workspaceService . roots ;
259
+ const destinationFileUri = await this . fileDialogService . showOpenDialog ( props , rootStat ) ;
260
+ if ( destinationFileUri ) {
261
+ const destinationFile = await this . fileSystem . getFileStat ( destinationFileUri . toString ( ) ) ;
262
+ if ( destinationFile && ! destinationFile . isDirectory ) {
263
+ await this . openSketchFilesInNewWindow ( destinationFileUri . toString ( ) ) ;
264
+ return destinationFileUri ;
265
+ }
266
+ }
267
+ return undefined ;
268
+ }
269
+
160
270
protected getCurrentWidget ( ) : EditorWidget | undefined {
161
271
let widget = this . editorManager . currentEditor ;
162
272
if ( ! widget ) {
0 commit comments