11'use strict' ;
22
3+ const { spawn } = require ( 'child_process' ) ;
34const electron = require ( 'electron' ) ;
45const { app, BrowserWindow, ipcMain} = electron ;
56const fs = require ( 'fs' ) ;
67
7- let { PythonShell} = require ( 'python-shell' )
8+ const WebSocket = require ( 'ws' ) ;
9+
10+
11+ const DEBUG = false ;
12+ const DEBUG_RENDER = false ;
813
9- const logger = new console . Console ( fs . createWriteStream ( `${ __dirname } /log.txt` ) ) ;
10- const python_options = fs . createReadStream ( `${ __dirname } /python_settings.json` )
1114
1215// Keep a global reference of the mainWindowdow object to avoid garbage collector
1316let 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/" ;
1422
1523function createMainWindow ( ) {
1624 // Create the browser mainWindow
@@ -22,13 +30,15 @@ function createMainWindow() {
2230 webPreferences : {
2331 nodeIntegration : true ,
2432 contextIsolation : false ,
25- }
33+ } ,
34+ slashes : true
2635 } ) ;
2736
2837 // Load the index page
2938 mainWindow . loadFile ( 'index.html' ) ;
3039
31- // mainWindow.openDevTools()
40+ if ( DEBUG || DEBUG_RENDER )
41+ mainWindow . openDevTools ( ) ;
3242
3343 // Link handler
3444 mainWindow . webContents . setWindowOpenHandler ( ( { url} ) => {
@@ -40,30 +50,62 @@ function createMainWindow() {
4050 mainWindow . on ( 'closed' , ( ) => {
4151 mainWindow = null ;
4252 } ) ;
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+
5668
5769app . on ( 'ready' , ( ) => {
58- emptySVGDir ( ) ;
70+ // emptySVGDir();
5971 createMainWindow ( ) ;
6072
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+
6193 ipcMain . on ( 'request-plot' , ( event , plotParams ) => {
6294 plot ( plotParams ) ;
6395 } )
6496 ipcMain . on ( 'request-code' , ( event , plotParams ) => {
6597 generateCode ( plotParams ) ;
6698 } )
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+ } )
67109} ) ;
68110
69111// disable menu
@@ -81,53 +123,79 @@ app.on('quit', () => {
81123 // do some additional cleanup
82124} ) ;
83125
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+ } ) ;
97132
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+ } ;
101172
102- function showPythonCode ( filename ) {
103- mainWindow . webContents . send ( 'show-code' , filename )
104- }
173+ function showPythonCode ( message ) {
174+ mainWindow . webContents . send ( 'show-code' , message ) ;
175+ } ;
105176
106177function 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