1- import { exec , spawn } from 'child_process' ;
1+ import { spawn } from 'child_process' ;
22import { join } from 'path' ;
3- import { Event , EventEmitter , ProviderResult , TreeDataProvider , TreeItem , TreeItemCollapsibleState , window } from 'vscode' ;
3+ import { Event , EventEmitter , ExtensionContext , ProviderResult , TreeDataProvider , TreeItem , TreeItemCollapsibleState , window } from 'vscode' ;
44import { state } from './extension' ;
55import { existsSync } from 'fs' ;
66
@@ -21,41 +21,54 @@ export interface Folder {
2121 sketches ?: Sketch [ ] ;
2222}
2323
24- export async function setupSidebar ( ) {
24+ export async function setupSidebar ( context : ExtensionContext ) {
2525 // TODO: Show welcome screens whilst we are starting Processing
26- // TODO: Open examples as read-only or in a temporary location
27- // TODO: Reload examples and sketchbook when Processing version changes
28- // TODO: Add cache to results to speed up loading
2926
30- setupExamples ( ) ;
31- setupSketchbook ( ) ;
27+ setupSketchTreeView ( 'sketchbook list' , 'processingSidebarSketchbookView' , context ) ;
28+ setupSketchTreeView ( 'contributions examples list' , 'processingSidebarExamplesView' , context , true ) ;
3229}
3330
34- async function setupExamples ( ) {
35- const examplesProvider = new ProcessingWindowDataProvider ( 'contributions examples list' ) ;
36- window . createTreeView ( 'processingSidebarExamplesView' , { treeDataProvider : examplesProvider } ) ;
37- }
38-
39- async function setupSketchbook ( ) {
40- const sketchbookProvider = new ProcessingWindowDataProvider ( 'sketchbook list' ) ;
41- window . createTreeView ( 'processingSidebarSketchbookView' , { treeDataProvider : sketchbookProvider } ) ;
31+ function setupSketchTreeView ( command : string , viewId : string , context : ExtensionContext , readonly = false ) {
32+ const provider = new ProcessingWindowDataProvider ( command , context , readonly ) ;
33+ window . createTreeView ( viewId , { treeDataProvider : provider } ) ;
4234}
4335
4436
4537class ProcessingWindowDataProvider implements TreeDataProvider < FolderTreeItem | SketchTreeItem > {
4638 constructor (
47- public readonly command : string
39+ public readonly command : string ,
40+ public readonly context : ExtensionContext ,
41+ public readonly readonly = false
4842 ) {
49- this . _folders = [ ] ;
43+ this . cached ( ) ;
5044 this . populate ( ) ;
45+ this . listen ( ) ;
5146 }
52- private _folders : Folder [ ] ;
47+ private _folders : Folder [ ] = [ ] ;
48+
49+ private _onDidChangeTreeData : EventEmitter < null > = new EventEmitter < null > ( ) ;
50+ readonly onDidChangeTreeData : Event < null > = this . _onDidChangeTreeData . event ;
5351
54- private _onDidChangeTreeData : EventEmitter < any > = new EventEmitter < any > ( ) ;
55- readonly onDidChangeTreeData : Event < any > = this . _onDidChangeTreeData . event ;
52+ async listen ( ) {
53+ state . onDidVersionChange . on ( null , async ( ) => {
54+ this . populate ( ) ;
55+ } ) ;
56+ }
57+
58+ async cached ( ) {
59+ const data = await this . context . globalState . get < string > ( `processing-tree-view-${ this . command } -cache` ) ;
60+ if ( data ) {
61+ try {
62+ this . _folders = JSON . parse ( data ) as Folder [ ] ;
63+ } catch ( e ) {
64+ console . error ( `Error parsing cached JSON: ${ e } ` ) ;
65+ }
66+ }
67+ this . _onDidChangeTreeData . fire ( null ) ;
68+ }
5669
5770 async populate ( ) {
58- this . _folders = await this . grabSketchesWithCommand ( this . command ) ;
71+ this . _folders = await this . grabSketches ( ) ;
5972 this . _onDidChangeTreeData . fire ( null ) ;
6073 }
6174
@@ -68,7 +81,7 @@ class ProcessingWindowDataProvider implements TreeDataProvider<FolderTreeItem |
6881 return this . _folders . map ( ( folder ) => new FolderTreeItem ( folder ) ) ?? [ ] ;
6982 } else {
7083 const sketches = element . folder . sketches ?. map ( ( sketch ) => {
71- return new SketchTreeItem ( sketch ) ;
84+ return new SketchTreeItem ( sketch , this . readonly ) ;
7285 } ) ?? [ ] ;
7386 const folders = element . folder . children ?. map ( ( folder ) => {
7487 return new FolderTreeItem ( folder ) ;
@@ -82,9 +95,9 @@ class ProcessingWindowDataProvider implements TreeDataProvider<FolderTreeItem |
8295 }
8396 }
8497
85- grabSketchesWithCommand ( command : string ) : Promise < Folder [ ] > {
98+ grabSketches ( ) : Promise < Folder [ ] > {
8699 return new Promise < Folder [ ] > ( ( resolve ) => {
87- const process = spawn ( state . selectedVersion . path , command . split ( ' ' ) ) ;
100+ const process = spawn ( state . selectedVersion . path , this . command . split ( ' ' ) ) ;
88101 let data = '' ;
89102 process . stdout . on ( 'data' , ( chunk ) => {
90103 data += chunk ;
@@ -96,7 +109,9 @@ class ProcessingWindowDataProvider implements TreeDataProvider<FolderTreeItem |
96109 return ;
97110 }
98111 try {
112+ this . context . globalState . update ( `processing-tree-view-${ this . command } -cache` , data ) ;
99113 const folders = JSON . parse ( data ) as Folder [ ] ;
114+
100115 resolve ( folders ) ;
101116 } catch ( e ) {
102117 console . error ( `Error parsing JSON: ${ e } ` ) ;
@@ -119,7 +134,8 @@ class FolderTreeItem extends TreeItem {
119134
120135class SketchTreeItem extends TreeItem {
121136 constructor (
122- public readonly sketch : Sketch
137+ public readonly sketch : Sketch ,
138+ public readonly readonly = false
123139 ) {
124140 const label = sketch . name ;
125141 super ( label , TreeItemCollapsibleState . None ) ;
@@ -128,8 +144,9 @@ class SketchTreeItem extends TreeItem {
128144 this . command = {
129145 command : 'processing.sketch.open' ,
130146 title : 'Open Sketch' ,
131- arguments : [ this . sketch . path ]
147+ arguments : [ this . sketch . path , this . readonly ]
132148 } ;
149+ // TODO: add right-click menu to open in new window, open containing folder, etc.
133150
134151 // TODO: Make showing a preview a toggleable setting
135152 const preview = `${ sketch . path } /${ sketch . name } .png` ;
0 commit comments