1
1
'use strict' ;
2
2
3
+ const { spawn } = require ( 'child_process' ) ;
3
4
const electron = require ( 'electron' ) ;
4
5
const { app, BrowserWindow, ipcMain} = electron ;
5
6
const fs = require ( 'fs' ) ;
6
7
7
- let { PythonShell} = require ( 'python-shell' )
8
+ const WebSocket = require ( 'ws' ) ;
9
+
10
+
11
+ const DEBUG = false ;
12
+ const DEBUG_RENDER = false ;
8
13
9
- const logger = new console . Console ( fs . createWriteStream ( `${ __dirname } /log.txt` ) ) ;
10
- const python_options = fs . createReadStream ( `${ __dirname } /python_settings.json` )
11
14
12
15
// Keep a global reference of the mainWindowdow object to avoid garbage collector
13
16
let mainWindow = null ;
17
+ let python_server_process = null ;
18
+ let phaseportrait_socket = null ;
19
+ // let mpl_websocket = null;
20
+ let FigId = null ;
21
+ let ws_uri = "ws://127.0.0.1:8080/" ;
14
22
15
23
function createMainWindow ( ) {
16
24
// Create the browser mainWindow
@@ -22,13 +30,15 @@ function createMainWindow() {
22
30
webPreferences : {
23
31
nodeIntegration : true ,
24
32
contextIsolation : false ,
25
- }
33
+ } ,
34
+ slashes : true
26
35
} ) ;
27
36
28
37
// Load the index page
29
38
mainWindow . loadFile ( 'index.html' ) ;
30
39
31
- // mainWindow.openDevTools()
40
+ if ( DEBUG || DEBUG_RENDER )
41
+ mainWindow . openDevTools ( ) ;
32
42
33
43
// Link handler
34
44
mainWindow . webContents . setWindowOpenHandler ( ( { url} ) => {
@@ -40,30 +50,62 @@ function createMainWindow() {
40
50
mainWindow . on ( 'closed' , ( ) => {
41
51
mainWindow = null ;
42
52
} ) ;
43
- }
44
-
45
- function emptySVGDir ( ) {
46
- fs . readdir ( `${ __dirname } /svg` , ( err , files ) => {
47
- if ( err ) throw err ;
48
- for ( const file of files ) {
49
- if ( file === 'default.svg' ) continue ;
50
- fs . unlinkSync ( `${ __dirname } /svg/${ file } ` , err => {
51
- if ( err ) throw err ;
52
- } ) ;
53
- }
54
- } ) ;
55
- }
53
+ } ;
54
+
55
+ // function emptySVGDir() {
56
+ // fs.readdir(`${__dirname}/svg`, (err, files) => {
57
+ // if (err) throw err;
58
+ // for (const file of files) {
59
+ // if (file === 'default.svg') continue;
60
+ // fs.unlinkSync(`${__dirname}/svg/${file}`, err => {
61
+ // if (err) throw err;
62
+ // });
63
+ // }
64
+ // });
65
+ // };
66
+
67
+
56
68
57
69
app . on ( 'ready' , ( ) => {
58
- emptySVGDir ( ) ;
70
+ // emptySVGDir();
59
71
createMainWindow ( ) ;
60
72
73
+ if ( ! DEBUG ) {
74
+ python_server_process = spawn ( 'python' , [ `${ __dirname } /phaseportrait-launcher.py` ] )
75
+ python_server_process . stdout . on ( 'data' , ( data ) => {
76
+ if ( DEBUG || DEBUG_RENDER ) console . log ( String ( data ) ) ;
77
+ FigId = String ( data ) . split ( ',' ) [ 1 ] ;
78
+ setupMPLWebSocket ( ) ;
79
+
80
+ if ( phaseportrait_socket === null ) {
81
+ setupPPWebSocket ( ) ;
82
+ } ;
83
+
84
+ updatePlot ( ) ;
85
+ } ) ;
86
+ }
87
+ else {
88
+ setupPPWebSocket ( ) ;
89
+ setupMPLWebSocket ( ) ;
90
+ updatePlot ( ) ;
91
+ }
92
+
61
93
ipcMain . on ( 'request-plot' , ( event , plotParams ) => {
62
94
plot ( plotParams ) ;
63
95
} )
64
96
ipcMain . on ( 'request-code' , ( event , plotParams ) => {
65
97
generateCode ( plotParams ) ;
66
98
} )
99
+ ipcMain . on ( 'save-configuration' , ( event , settings ) => {
100
+ fs . writeFileSync ( "settings.json" , JSON . stringify ( settings ) , 'utf-8' )
101
+ } )
102
+ ipcMain . on ( 'request-configuration' , ( e ) => {
103
+ fs . readFile ( "settings.json" , ( err , data ) => {
104
+ let settings = JSON . parse ( data ) ;
105
+ if ( DEBUG || DEBUG_RENDER ) console . log ( settings ) ;
106
+ mainWindow . webContents . send ( 'load-configuration' , settings ) ;
107
+ } ) ;
108
+ } )
67
109
} ) ;
68
110
69
111
// disable menu
@@ -81,53 +123,79 @@ app.on('quit', () => {
81
123
// do some additional cleanup
82
124
} ) ;
83
125
84
- function runPythonScript ( plot = true , plotParams = [ ] ) {
85
- return new Promise ( function ( success , nosuccess ) {
86
- let options = {
87
- args : [ plot ? '--plot' : '--code' ,
88
- JSON . stringify ( plotParams ) ]
89
- }
90
- PythonShell . run ( `${ __dirname } /phaseportrait-launcher.py` , options , ( err , results ) => {
91
- if ( err ) nosuccess ( err ) ;
92
- success ( results )
93
- } ) ;
94
- } ) ;
95
- }
96
-
126
+ app . on ( 'window-all-closed' , ( ) => {
127
+ // For MacOs
128
+ if ( process . platform !== 'darwin' ) {
129
+ app . quit ( )
130
+ }
131
+ } ) ;
97
132
98
- function updatePlotSVG ( filename ) {
99
- mainWindow . webContents . send ( 'load-svg' , filename )
100
- }
133
+ function updatePlot ( ) {
134
+ mainWindow . webContents . send ( 'load-plot' , FigId ) ;
135
+ } ;
136
+
137
+ function get_websocket_type ( ) {
138
+ if ( typeof WebSocket !== 'undefined' ) {
139
+ return WebSocket ;
140
+ } else if ( typeof MozWebSocket !== 'undefined' ) {
141
+ return MozWebSocket ;
142
+ } else {
143
+ alert (
144
+ 'Your browser does not have WebSocket support. ' +
145
+ 'Please try Chrome, Safari or Firefox ≥ 6. ' +
146
+ 'Firefox 4 and 5 are also supported but you ' +
147
+ 'have to enable WebSockets in about:config.'
148
+ ) ;
149
+ }
150
+ } ;
151
+
152
+ function setupMPLWebSocket ( ) {
153
+ let mpl_websocket_type = get_websocket_type ( ) ;
154
+ // mpl_websocket = new mpl_websocket_type(`${ws_uri}ws`);
155
+ } ;
156
+
157
+ function setupPPWebSocket ( ) {
158
+ let web_socket_type = get_websocket_type ( ) ;
159
+ phaseportrait_socket = new web_socket_type ( `${ ws_uri } pp` ) ;
160
+ // phaseportrait_socket.onerror = ...;
161
+ // phaseportrait_socket.onopen = ...;
162
+ // phaseportrait_socket.onmessage = ...;
163
+ phaseportrait_socket . onclose = function ( ) {
164
+ setTimeout ( setupPPWebSocket , 2000 ) ;
165
+
166
+ } ;
167
+ phaseportrait_socket . on ( "error" , ( err ) => {
168
+ // logger.log('error', error);
169
+ showError ( err ) ;
170
+ } ) ;
171
+ } ;
101
172
102
- function showPythonCode ( filename ) {
103
- mainWindow . webContents . send ( 'show-code' , filename )
104
- }
173
+ function showPythonCode ( message ) {
174
+ mainWindow . webContents . send ( 'show-code' , message ) ;
175
+ } ;
105
176
106
177
function showError ( message ) {
107
- mainWindow . webContents . send ( 'show-error' , message )
108
- }
109
-
110
- function plot ( params ) {
111
- runPythonScript ( true , params )
112
- . then ( ( data ) => {
113
- if ( data == 0 ) {
114
- throw Error ( 'Error: Invalid function' ) ;
115
- }
116
- updatePlotSVG ( data ) ;
117
- } )
118
- . catch ( ( error ) => {
119
- logger . log ( 'error' , error ) ;
120
- showError ( error ) ;
121
- } ) ;
122
- }
123
-
124
- function generateCode ( params ) {
125
- runPythonScript ( false , params )
126
- . then ( ( data ) => {
127
- showPythonCode ( data . join ( '\n' ) )
128
- } )
129
- . catch ( ( error ) => {
130
- logger . log ( 'error' , error ) ;
131
- showError ( error ) ;
132
- } ) ;
133
- }
178
+ mainWindow . webContents . send ( 'show-error' , message ) ;
179
+ } ;
180
+
181
+ function sendParamsToPython ( plot = true , plotParams = [ ] ) {
182
+ plotParams [ "phaseportrait_request" ] = plot ? '--plot' : '--code' ;
183
+ phaseportrait_socket . send ( JSON . stringify ( plotParams ) )
184
+ } ;
185
+
186
+ function plot ( plotParams ) {
187
+ phaseportrait_socket . removeAllListeners ( "message" ) ;
188
+ phaseportrait_socket . on ( "message" , ( data ) => {
189
+ if ( DEBUG || DEBUG_RENDER ) console . log ( String ( data ) ) ;
190
+ updatePlot ( data . toString ( ) ) ;
191
+ } ) ;
192
+ sendParamsToPython ( true , plotParams ) ;
193
+ } ;
194
+
195
+ function generateCode ( codeParams ) {
196
+ phaseportrait_socket . removeAllListeners ( "message" ) ;
197
+ phaseportrait_socket . on ( "message" , ( data ) => {
198
+ showPythonCode ( data . toString ( ) ) ;
199
+ } ) ;
200
+ sendParamsToPython ( false , codeParams ) ;
201
+ } ;
0 commit comments