Compare commits
88 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 47c0f7a319 | |||
| 61b91707cf | |||
| 25140790fd | |||
| e629ed0cb4 | |||
| df3fe3e2a4 | |||
| a158402402 | |||
| 9d71be46ea | |||
| 1c5d28bba8 | |||
| d2ff626c8c | |||
| b18ec1c5fe | |||
| 065fc74269 | |||
| 43c3f75764 | |||
| e5a0a8048a | |||
| 3c7d8a0e65 | |||
| 12186a8f2f | |||
| 84d97b95c9 | |||
| a7ffcaeefe | |||
| 08238d61e8 | |||
| f473e04e9a | |||
| 372b10944d | |||
| c738032ada | |||
| e802421bbd | |||
| 1e25128009 | |||
| c2f0513f4a | |||
| d865e7ef08 | |||
| bf13f6cb76 | |||
| b2a59afa36 | |||
| 0a86dad75f | |||
| 5b7b3dd73a | |||
| 96a42156d4 | |||
| 7a61a98ca1 | |||
| edbcd9b3dc | |||
| 2fff23ebe8 | |||
| 407440aa35 | |||
| 1e89b4efef | |||
| 98ba507e1d | |||
| b9bd18eed0 | |||
| cfdd7db2ec | |||
| bfe8ace466 | |||
| d68655aaed | |||
| 66a1387ed0 | |||
| 7ffa9547f0 | |||
| ce5aafd076 | |||
| 78fb7c616d | |||
| 163935e2ba | |||
| 632ccf3867 | |||
| 76988379d9 | |||
| 400a507ca2 | |||
| 2589274f73 | |||
| 8547e2997c | |||
| 9916d70d84 | |||
| 183e2ac360 | |||
| 86992133f0 | |||
| 98e79d861f | |||
| 7c9360875c | |||
| 4e68962937 | |||
| 3527d57b40 | |||
| 9551cbdd01 | |||
| 4683945a71 | |||
| 0e0aef010f | |||
| af500b2918 | |||
| ecf0105c73 | |||
| d3de8b2365 | |||
| d7c1ec7fee | |||
| 644d0479d8 | |||
| 1bb1972e9e | |||
| 5fa07b0e39 | |||
| 824f24261b | |||
| 306fe57d32 | |||
| d2c985ed87 | |||
| 42d131ebae | |||
| e286702731 | |||
| f6536d961e | |||
| 349b625b98 | |||
| 984aef11cd | |||
| ccf8170c8b | |||
| 0295d9b531 | |||
| c9d3132cdb | |||
| 95ddff56a2 | |||
| 961fc41ed6 | |||
| adc627efce | |||
| 27077c802d | |||
| b65cf52fb4 | |||
| e3aad63e85 | |||
| 5ebcdfda2f | |||
| 6cc166a17a | |||
| 8f748e4362 | |||
| 02e960dd84 |
@@ -118,4 +118,5 @@ dist
|
||||
.pnp.*
|
||||
|
||||
# my additions
|
||||
package-lock.json
|
||||
*~
|
||||
|
||||
@@ -10,7 +10,7 @@ an application for performing [Monte Carlo] simulations of ion implantation.
|
||||
* The code is maintained by the Low Energy Muons ([LEM]) group at the Paul Scherrer Institute ([PSI]).
|
||||
* The [GUI] is written in [Node.js], [JavaScript] and [Electron].
|
||||
* The binary (statically linked) from the [Fortran] code is also included.
|
||||
* Linux packages can be generated locally from the current source tree.
|
||||
* [RPM] and [DEB] packages are also included.
|
||||
|
||||
Further information can be found in the following publications:
|
||||
|
||||
@@ -39,8 +39,7 @@ Further information can be found in the following publications:
|
||||
|
||||
### Installation ###
|
||||
|
||||
Packages are not stored in this repository. You can either run the application
|
||||
directly from source or build Linux packages locally as described below.
|
||||
For a simple installation you may use the included RPM or Debian packages which come with statically linked binaries. See instructions below if you prefer a manual installation.
|
||||
|
||||
###### Fortran code compilation ######
|
||||
|
||||
@@ -49,18 +48,11 @@ Install the `gfortran` compiler, then:
|
||||
```bash
|
||||
cd trimsp/fortran
|
||||
make
|
||||
make install
|
||||
```
|
||||
|
||||
This creates the `trimspNL` binary in the repository root. For packaged
|
||||
Electron builds, copy or rebuild it into:
|
||||
|
||||
```text
|
||||
resources/bin/trimspNL
|
||||
```
|
||||
|
||||
The application will prefer that bundled copy when running from a packaged
|
||||
install. During development it can still use a local checkout copy or a
|
||||
`trimspNL` binary found in the configured path or in `PATH`.
|
||||
|
||||
This will install the `trimspNL` binary in `/usr/local/bin`,
|
||||
but it can be moved to any other directory in your `PATH`.
|
||||
|
||||
###### Running the GUI ######
|
||||
|
||||
@@ -76,114 +68,6 @@ npm start
|
||||
Note: you do not need to run `npm install` every time.
|
||||
Next time you can simply run `npm start` only.
|
||||
|
||||
###### Building RPM and DEB packages ######
|
||||
|
||||
Install [Node.js] (`nodejs`, `nodejs-libs` and `npm`), then run:
|
||||
|
||||
```bash
|
||||
cd trimsp
|
||||
cp trimspNL resources/bin/trimspNL
|
||||
npm install
|
||||
npm run make
|
||||
```
|
||||
|
||||
This uses Electron Forge to build Linux packages from the current checkout.
|
||||
The packaged application bundles `resources/bin/trimspNL` inside the app
|
||||
resources, so make sure that file exists and is up to date before packaging.
|
||||
|
||||
The generated files are written under:
|
||||
|
||||
```text
|
||||
out/make/deb/x64/
|
||||
out/make/rpm/x64/
|
||||
```
|
||||
|
||||
Typical output files are:
|
||||
|
||||
```text
|
||||
out/make/deb/x64/trimsp_<version>_amd64.deb
|
||||
out/make/rpm/x64/TrimSP-<version>-1.x86_64.rpm
|
||||
```
|
||||
|
||||
To generate matching checksum sidecar files for each generated package, run:
|
||||
|
||||
```bash
|
||||
npm run checksums
|
||||
```
|
||||
|
||||
This creates files next to each package, for example:
|
||||
|
||||
```text
|
||||
out/make/rpm/x64/TrimSP-<version>-1.x86_64.rpm.md5
|
||||
out/make/rpm/x64/TrimSP-<version>-1.x86_64.rpm.sha256
|
||||
```
|
||||
|
||||
If you only want one checksum type, you can also run:
|
||||
|
||||
```bash
|
||||
npm run checksums:md5
|
||||
npm run checksums:sha256
|
||||
```
|
||||
|
||||
Depending on the host system, additional packaging tools may be required for
|
||||
the RPM/DEB build chain.
|
||||
|
||||
###### Building a Flatpak ######
|
||||
|
||||
Install the Flatpak build tools in addition to [Node.js]:
|
||||
|
||||
```bash
|
||||
flatpak
|
||||
flatpak-builder
|
||||
elfutils
|
||||
```
|
||||
|
||||
Then run:
|
||||
|
||||
```bash
|
||||
cd trimsp
|
||||
cp fortran/trimspNL resources/bin/trimspNL
|
||||
npm install
|
||||
npm run make:flatpak
|
||||
```
|
||||
|
||||
This uses Electron Forge's Flatpak maker and writes the resulting `.flatpak`
|
||||
under:
|
||||
|
||||
```text
|
||||
out/make/flatpak/x86_64/
|
||||
```
|
||||
|
||||
Checksum sidecar files can be generated afterward with:
|
||||
|
||||
```bash
|
||||
npm run checksums
|
||||
```
|
||||
|
||||
The current Flatpak config grants access to the home directory and `/tmp`,
|
||||
which matches how the packaged app currently handles simulation input/output.
|
||||
|
||||
###### Deploying on a web server ######
|
||||
|
||||
The browser version requires a server-side setup in addition to the static
|
||||
HTML/JavaScript files.
|
||||
|
||||
In particular:
|
||||
|
||||
* the browser build uses `TrimSPweb.js` rather than the Electron-specific
|
||||
`TrimSPelec.js`
|
||||
* the simulation backend must be available on the server
|
||||
* a web-exposed helper/CGI layer is required to create input files, run the
|
||||
backend, and return the generated output
|
||||
|
||||
Notes:
|
||||
|
||||
* this repository does not currently include the CGI/backend helper used by
|
||||
the online deployment
|
||||
* a plain static web server is therefore not sufficient for running web
|
||||
simulations from this checkout
|
||||
* static hosting can still be used to test page loading only
|
||||
|
||||
### Contact ###
|
||||
|
||||
Zaher Salman <zaher.salman@psi.ch>
|
||||
|
||||
+24
-41
@@ -9,7 +9,7 @@
|
||||
<script src="TrimSPlib.js"></script>
|
||||
<script src="myplots.js"></script>
|
||||
<!script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
|
||||
<title>TRIM.SP</title>
|
||||
<title>Trim.SP</title>
|
||||
</head>
|
||||
<body onresize="resizePl()" onload="adjust_table();adjust_scans();">
|
||||
<table style="width: 100%;">
|
||||
@@ -30,16 +30,15 @@
|
||||
<td><label>File name prefix:</label></td>
|
||||
<td>
|
||||
<input name="fileNamePrefix" id="fileNamePrefix" type="text" style="width:70%" value="SrTiO3"/>
|
||||
<input name="trimPath" id="trimPath" type="hidden"/>
|
||||
<input name="trimPath" id="trimPath" type="text" style="width:70%;visibility:hidden;"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="FolderRow">
|
||||
<td><label>Save folder:</label></td>
|
||||
<td>
|
||||
<input type="text" disabled style="width:70%" id="workPath" name="workPath" title="Use Browse to select the save folder" />
|
||||
<input type="text" style="width:70%" id="workPath" name="workPath" readonly/>
|
||||
<input type="button" value="Browse"
|
||||
id="browseFolde" onclick="browseForFolder();">
|
||||
<input type="file" id="folderPicker" style="display:none" webkitdirectory directory>
|
||||
id="browseFolde" onclick="ipcRenderer.send('browseFolder');">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -60,7 +59,6 @@
|
||||
<td><select name="ProjType" id="ProjType" onchange="ProjSmartDefaults()" onload="ProjSmartDefaults()">
|
||||
<option selected="selected" value="muon">muon</option>
|
||||
<option value="Li-8">Li-8</option>
|
||||
<option value="Be-11">Be-11</option>
|
||||
<option value="B-12">B-12</option>
|
||||
<option value="Mg-31">Mg-31</option>
|
||||
<option value="H">H</option>
|
||||
@@ -312,23 +310,14 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tooltip">
|
||||
Stopping Power<br>Coefficients
|
||||
<input type="checkbox" id="flagICRU" checked>
|
||||
<span class="tooltiptext">
|
||||
Data source for the Varelas-Biersack parameterization of electronic
|
||||
stopping cross-sections for proton-like projectiles implanted in
|
||||
elemental targets:
|
||||
<ol>
|
||||
<li value="1">Table 1 in Anderson & Ziegler (1977).</li>
|
||||
<li value="2">Table 3.1 in ICRU Report 49 (1993).</li>
|
||||
<li value="3">Table II in McFadden et al. (2023) and McFadden et al. (unpublished).</li>
|
||||
</ol>
|
||||
Note: While option 3 contains the most up-to-date values, it currently
|
||||
does not contain entries for every target element. For elements with
|
||||
missing data, values from option 2 are taken instead.
|
||||
</span>
|
||||
Force the TRIM.SP code to use stopping power
|
||||
parameters from the old ICRU tables.
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input name="flagSPC" id="flagSPC" type="number" step="1" min="1" max="3" value="2">
|
||||
Use ICRU parameters
|
||||
</td>
|
||||
<td class="tooltip">
|
||||
IRL
|
||||
@@ -349,7 +338,9 @@
|
||||
</tr>
|
||||
</table>
|
||||
<p>
|
||||
For further details see:<br>
|
||||
For further details see:
|
||||
</p>
|
||||
<p>
|
||||
W. Eckstein, <i>Computer Simulation of Ion-Solid Interactions</i>,<br>
|
||||
Springer Series in Materials Science, Vol. 10 (Springer-Verlag, Berlin, 1991).<br>
|
||||
<a href="https://doi.org/10.1007/978-3-642-73513-4">
|
||||
@@ -359,36 +350,28 @@
|
||||
</div>
|
||||
</div>
|
||||
</td></tr>
|
||||
<tr style="width: 100%;//visibility: hidden;">
|
||||
<td>
|
||||
<div class="w3-light-grey">
|
||||
<div id="pBar" class="w3-container w3-green w3-center" style="width:0%">0%</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div id="statusBar" class="status-bar">
|
||||
<span class="status-item"><strong>Folder:</strong> <span id="statusWorkPath">-</span></span>
|
||||
<span class="status-item"><strong>Backend:</strong> <span id="statusBackend">-</span></span>
|
||||
<span class="status-item"><strong>Last save:</strong> <span id="statusLastSave">Not saved yet</span></span>
|
||||
<span class="status-item"><strong>Run:</strong> <span id="statusRun">Idle</span></span>
|
||||
<div class="status-progress">
|
||||
<div class="status-progress-track">
|
||||
<div id="pBar" class="status-progress-fill">0%</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script>
|
||||
|
||||
let workPath = document.getElementById("workPath");
|
||||
let webOrApp = amIWeb();
|
||||
// If empty or undefined use local folder as default
|
||||
if (workPath.value == '' || workPath.value == undefined ) {
|
||||
if (webOrApp) {
|
||||
workPath.value = '/tmp';
|
||||
} else {
|
||||
workPath.value = process.cwd();
|
||||
}
|
||||
}
|
||||
if (typeof syncStatusBar === 'function') {
|
||||
syncStatusBar();
|
||||
// workPath.value = process.cwd();
|
||||
workPath.value = '/tmp';
|
||||
//app.setPath('temp',process.cwd());
|
||||
}
|
||||
// Open the default Layers tab
|
||||
document.getElementById("btnLayers").click();
|
||||
|
||||
let webOrApp = amIWeb();
|
||||
|
||||
if (webOrApp) {
|
||||
console.log('this script is not running in Node.js');
|
||||
|
||||
+15
-87
@@ -5,7 +5,7 @@ const Plotly = require('plotly.js-dist');
|
||||
const ipcRenderer = require('electron').ipcRenderer;
|
||||
const fs = require('fs');
|
||||
const exec = require('child_process').execSync;
|
||||
const path = require('path');
|
||||
const remote = require('electron').remote;
|
||||
|
||||
function getFiles(dir, filelist){
|
||||
fileList = [];
|
||||
@@ -73,70 +73,8 @@ function fileExists(filename) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
function getTrimBinaryPath(configuredPath) {
|
||||
const candidates = [];
|
||||
if (configuredPath) {
|
||||
candidates.push(path.join(configuredPath, "trimspNL"));
|
||||
}
|
||||
if (process.resourcesPath) {
|
||||
candidates.push(path.join(process.resourcesPath, "bin", "trimspNL"));
|
||||
candidates.push(path.join(process.resourcesPath, "trimspNL"));
|
||||
}
|
||||
candidates.push(path.join(process.cwd(), "trimspNL"));
|
||||
|
||||
for (const candidate of candidates) {
|
||||
if (fileExists(candidate)) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
return "trimspNL";
|
||||
}
|
||||
|
||||
function setWorkFolder(foldername) {
|
||||
const folder = Array.isArray(foldername) ? foldername[0] : foldername;
|
||||
if (folder) {
|
||||
document.getElementById("workPath").value = folder;
|
||||
if (typeof updateStatusBar === 'function') {
|
||||
updateStatusBar({ workPath: folder });
|
||||
}
|
||||
ipcRenderer.send('updateWorkPath', folder);
|
||||
try {
|
||||
// Change process directory
|
||||
process.chdir(folder);
|
||||
} catch (err) {
|
||||
console.log('Failed to change directory:', err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function browseForFolder() {
|
||||
ipcRenderer.send('browseFolder');
|
||||
}
|
||||
|
||||
function fallbackBrowseForFolder() {
|
||||
const picker = document.getElementById("folderPicker");
|
||||
if (!picker) { return; }
|
||||
picker.value = '';
|
||||
picker.click();
|
||||
}
|
||||
|
||||
function firstLoad() {
|
||||
document.getElementById("trimPath").value = process.cwd();
|
||||
if (typeof syncStatusBar === 'function') {
|
||||
syncStatusBar();
|
||||
}
|
||||
|
||||
const folderPicker = document.getElementById("folderPicker");
|
||||
if (folderPicker) {
|
||||
folderPicker.addEventListener('change', function(event) {
|
||||
const files = event.target.files;
|
||||
if (!files || files.length === 0) {
|
||||
return;
|
||||
}
|
||||
const folder = path.dirname(files[0].path);
|
||||
setWorkFolder([folder]);
|
||||
});
|
||||
}
|
||||
document.getElementById("trimPath").value = remote.getGlobal('path');
|
||||
|
||||
// Catch calls for open file
|
||||
ipcRenderer.on('openFile', function(event, filename) {
|
||||
@@ -151,31 +89,22 @@ function firstLoad() {
|
||||
|
||||
// Catch calls for selectfolder
|
||||
ipcRenderer.on('selectFolder', function(event, foldername) {
|
||||
setWorkFolder(foldername);
|
||||
if (foldername.length != 0) {
|
||||
document.getElementById("workPath").value = foldername[0];
|
||||
// Change process directory
|
||||
process.chdir(foldername[0]);
|
||||
}
|
||||
console.log("currentdir",process.cwd());
|
||||
});
|
||||
// Catch calls for save as
|
||||
ipcRenderer.on('saveFile', function(event, filename) {
|
||||
const workPath = document.getElementById("workPath").value || process.cwd();
|
||||
if (filename === undefined || filename === null) { return; }
|
||||
// If filename is empty use default value in the selected work folder
|
||||
if (filename == '') {filename = path.join(workPath, 'TrimSP.cfg');}
|
||||
if (path.extname(filename) === '') {
|
||||
filename += '.cfg';
|
||||
}
|
||||
// If filename is empty use default value
|
||||
if (filename == '') {filename='TrimSP.cfg';}
|
||||
// Get values from all fields and prepare config file
|
||||
let trimSPcfg=prep_cfg(0);
|
||||
// Save file to filename
|
||||
console.log('Save file to '+filename);
|
||||
try {
|
||||
fs.writeFileSync(filename, trimSPcfg, 'utf-8');
|
||||
if (typeof updateStatusBar === 'function') {
|
||||
updateStatusBar({ lastSave: filename });
|
||||
}
|
||||
if (typeof showTransientWarning === 'function') {
|
||||
showTransientWarning('Saved configuration to ' + filename, document.getElementById('workPath'), 4000);
|
||||
}
|
||||
}
|
||||
try { fs.writeFileSync(filename, trimSPcfg, 'utf-8'); }
|
||||
catch(e) { alert('Failed to save the file !'); }
|
||||
});
|
||||
// Catch calls for plotProf
|
||||
@@ -195,11 +124,10 @@ function firstLoad() {
|
||||
});
|
||||
// Catch clicks for Browse button
|
||||
ipcRenderer.on('browseFolder', function(event, foldername) {
|
||||
console.log('browseFolder reply', foldername);
|
||||
setWorkFolder(foldername);
|
||||
});
|
||||
|
||||
ipcRenderer.on('browseFolderFallback', function() {
|
||||
fallbackBrowseForFolder();
|
||||
if (foldername.length != 0) {
|
||||
document.getElementById("workPath").value = foldername[0];
|
||||
// Change process directory
|
||||
process.chdir(foldername[0]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+867
-3349
File diff suppressed because it is too large
Load Diff
@@ -19,27 +19,21 @@ td {
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.guitable tr:last-child td:first-child {
|
||||
border-bottom-left-radius: 12px;
|
||||
}
|
||||
|
||||
.guitable tr:last-child td:last-child {
|
||||
border-bottom-right-radius: 12px;
|
||||
}
|
||||
|
||||
.guitable tr:first-child td:first-child {
|
||||
border-top-left-radius: 12px;
|
||||
}
|
||||
|
||||
.guitable tr:first-child td:last-child {
|
||||
border-top-right-radius: 12px;
|
||||
}
|
||||
|
||||
.guitable tr:nth-child(odd) {
|
||||
background-color: #DDDDDD;
|
||||
}
|
||||
|
||||
.guitable tr:nth-child(even) {
|
||||
background-color: #DDDDDD;
|
||||
}
|
||||
@@ -50,323 +44,161 @@ td {
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 700px) {
|
||||
|
||||
/* For tablets: */
|
||||
.col-s-1 {
|
||||
width: 50%;
|
||||
background-color: #DDDDDD;
|
||||
}
|
||||
|
||||
.col-s-2 {
|
||||
width: 50%;
|
||||
background-color: #DDDDDD;
|
||||
}
|
||||
|
||||
.col-s-full {
|
||||
width: 100%;
|
||||
background-color: #F2F2F2;
|
||||
}
|
||||
|
||||
.col-s-1 {width: 50%;background-color: #DDDDDD;}
|
||||
.col-s-2 {width: 50%;background-color: #DDDDDD;}
|
||||
.col-s-full {width: 100%;background-color: #F2F2F2;}
|
||||
[class*="col-"] {
|
||||
width: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 990px) {
|
||||
/* For desktop: */
|
||||
.col-1 {width: 50%;background-color: #F2F2F2;}
|
||||
.col-2 {width: 50%;background-color: #F2F2F2;}
|
||||
.col-full {width: 100%;background-color: #F2F2F2;}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 990px) {
|
||||
[class*="col-"] {
|
||||
float: left;
|
||||
padding: 5px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* For desktop: */
|
||||
.col-1 {
|
||||
width: 50%;
|
||||
background-color: #F2F2F2;
|
||||
}
|
||||
.row::after {
|
||||
content: "";
|
||||
clear: both;
|
||||
display: table;
|
||||
}
|
||||
|
||||
.col-2 {
|
||||
width: 50%;
|
||||
background-color: #F2F2F2;
|
||||
}
|
||||
.group_name {
|
||||
padding-left:1em;
|
||||
padding-right:1em;
|
||||
font-size:105%;
|
||||
font-weight:bold;
|
||||
width: 1%;
|
||||
white-space: nowrap;
|
||||
/* text-align: center; */
|
||||
}
|
||||
.yellow_td {
|
||||
padding-left:1em;
|
||||
padding-right:1em;
|
||||
background-color: yellow;
|
||||
width: 1%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.gray_td {
|
||||
padding-left:1em;
|
||||
padding-right:1em;
|
||||
background-color: gray;
|
||||
width: 1%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.nocol_td {
|
||||
padding-left:1em;
|
||||
padding-right:1em;
|
||||
width: 1%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.col-full {
|
||||
width: 100%;
|
||||
background-color: #F2F2F2;
|
||||
}
|
||||
}
|
||||
/* Style the tab */
|
||||
.tab {
|
||||
overflow: hidden;
|
||||
border: 1px solid #ccc;
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
[class*="col-"] {
|
||||
float: left;
|
||||
padding: 5px;
|
||||
border: none;
|
||||
}
|
||||
/* Style the buttons that are used to open the tab content */
|
||||
.tab button {
|
||||
background-color: inherit;
|
||||
float: left;
|
||||
border: none;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
padding: 14px 16px;
|
||||
transition: 0.3s;
|
||||
font-size:105%;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
.row::after {
|
||||
content: "";
|
||||
clear: both;
|
||||
display: table;
|
||||
}
|
||||
/* Change background color of buttons on hover */
|
||||
.tab button:hover {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
/* Create an active/current tablink class */
|
||||
.tab button.active {
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
.transient-warning {
|
||||
position: fixed;
|
||||
max-width: 360px;
|
||||
padding: 10px 14px;
|
||||
background-color: #fff4cc;
|
||||
border: 1px solid #c5a100;
|
||||
border-radius: 8px;
|
||||
color: #4d3b00;
|
||||
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
|
||||
font-size: 0.95rem;
|
||||
line-height: 1.35;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition: opacity 0.25s ease;
|
||||
z-index: 1000;
|
||||
}
|
||||
/* Style the tab content */
|
||||
.tabcontent {
|
||||
display: none;
|
||||
padding: 6px 12px;
|
||||
border: 1px solid #ccc;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.tabcontent {
|
||||
/* animation: fadeEffect 1s; /* Fading effect takes 1 second */
|
||||
}
|
||||
|
||||
/* Go from zero to full opacity */
|
||||
@keyframes fadeEffect {
|
||||
from {opacity: 0;}
|
||||
to {opacity: 1;}
|
||||
}
|
||||
|
||||
.transient-warning.visible {
|
||||
opacity: 1;
|
||||
}
|
||||
/* Chrome, Safari, Opera */
|
||||
@-webkit-keyframes example {
|
||||
0% {background-color:red; left:20px; top:0px;}
|
||||
25% {background-color:orange; left:25px; top:0px;}
|
||||
50% {background-color:green; left:30px; top:0px;}
|
||||
75% {background-color:orange; left:25px; top:0px;}
|
||||
100% {background-color:red; left:20px; top:0px;}
|
||||
}
|
||||
|
||||
.estimated-density {
|
||||
background-color: #fff4cc;
|
||||
border: 1px solid #c5a100;
|
||||
}
|
||||
/* Standard syntax */
|
||||
@keyframes example {
|
||||
0% {background-color:red; left:20px; top:0px;}
|
||||
25% {background-color:orange; left:25px; top:0px;}
|
||||
50% {background-color:green; left:30px; top:0px;}
|
||||
75% {background-color:orange; left:25px; top:0px;}
|
||||
100% {background-color:red; left:20px; top:0px;}
|
||||
}
|
||||
|
||||
.status-bar {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px 16px;
|
||||
align-items: center;
|
||||
padding: 8px 14px;
|
||||
background-color: #eef2f5;
|
||||
border-top: 1px solid #b8c3cc;
|
||||
color: #23313d;
|
||||
font-size: 0.88rem;
|
||||
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.08);
|
||||
z-index: 900;
|
||||
}
|
||||
#myBar {
|
||||
width: 10%;
|
||||
height: 30px;
|
||||
background-color: #4CAF50;
|
||||
text-align: center; /* To center it horizontally (if you want) */
|
||||
line-height: 30px; /* To center it vertically */
|
||||
color: white;
|
||||
}
|
||||
|
||||
.status-item {
|
||||
min-width: 180px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
/* Tooltip container */
|
||||
.tooltip {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
/* border-bottom: 1px dotted black; /* If you want dots under the hoverable text */
|
||||
}
|
||||
|
||||
.status-item strong {
|
||||
color: #10202c;
|
||||
}
|
||||
/* Tooltip text */
|
||||
.tooltip .tooltiptext {
|
||||
visibility: hidden;
|
||||
width: 320px;
|
||||
background-color: black;
|
||||
color: #fff;
|
||||
text-align: left;
|
||||
padding: 5px;
|
||||
border-radius: 6px;
|
||||
|
||||
/* Position the tooltip text - see examples below! */
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.status-progress {
|
||||
flex: 1 1 260px;
|
||||
min-width: 220px;
|
||||
}
|
||||
|
||||
.status-progress-track {
|
||||
width: 100%;
|
||||
height: 22px;
|
||||
background-color: #d7dee5;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #b8c3cc;
|
||||
}
|
||||
|
||||
.status-progress-fill {
|
||||
width: 0%;
|
||||
height: 100%;
|
||||
background-color: #2e8b57;
|
||||
color: black;
|
||||
padding-left: 3px;
|
||||
text-align: center;
|
||||
line-height: 20px;
|
||||
font-size: 0.78rem;
|
||||
font-weight: 600;
|
||||
transition: width 0.2s ease;
|
||||
}
|
||||
|
||||
.group_name {
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
font-size: 105%;
|
||||
font-weight: bold;
|
||||
width: 1%;
|
||||
white-space: nowrap;
|
||||
/* text-align: center; */
|
||||
}
|
||||
|
||||
.yellow_td {
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
background-color: yellow;
|
||||
width: 1%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.gray_td {
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
background-color: gray;
|
||||
width: 1%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.nocol_td {
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
width: 1%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Style the tab */
|
||||
.tab {
|
||||
overflow: hidden;
|
||||
border: 1px solid #ccc;
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
/* Style the buttons that are used to open the tab content */
|
||||
.tab button {
|
||||
background-color: inherit;
|
||||
float: left;
|
||||
border: none;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
padding: 14px 16px;
|
||||
transition: 0.3s;
|
||||
font-size: 105%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Change background color of buttons on hover */
|
||||
.tab button:hover {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
/* Create an active/current tablink class */
|
||||
.tab button.active {
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
/* Style the tab content */
|
||||
.tabcontent {
|
||||
display: none;
|
||||
padding: 6px 12px;
|
||||
border: 1px solid #ccc;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
/* Go from zero to full opacity */
|
||||
@keyframes fadeEffect {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Chrome, Safari, Opera */
|
||||
@-webkit-keyframes example {
|
||||
0% {
|
||||
background-color: red;
|
||||
left: 20px;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
25% {
|
||||
background-color: orange;
|
||||
left: 25px;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
50% {
|
||||
background-color: green;
|
||||
left: 30px;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
75% {
|
||||
background-color: orange;
|
||||
left: 25px;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-color: red;
|
||||
left: 20px;
|
||||
top: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Standard syntax */
|
||||
@keyframes example {
|
||||
0% {
|
||||
background-color: red;
|
||||
left: 20px;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
25% {
|
||||
background-color: orange;
|
||||
left: 25px;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
50% {
|
||||
background-color: green;
|
||||
left: 30px;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
75% {
|
||||
background-color: orange;
|
||||
left: 25px;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-color: red;
|
||||
left: 20px;
|
||||
top: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
#myBar {
|
||||
width: 10%;
|
||||
height: 30px;
|
||||
background-color: #4CAF50;
|
||||
text-align: center;
|
||||
/* To center it horizontally (if you want) */
|
||||
line-height: 30px;
|
||||
/* To center it vertically */
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Tooltip container */
|
||||
.tooltip {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
/* border-bottom: 1px dotted black; /* If you want dots under the hoverable text */
|
||||
}
|
||||
|
||||
/* Tooltip text */
|
||||
.tooltip .tooltiptext {
|
||||
visibility: hidden;
|
||||
width: 320px;
|
||||
background-color: black;
|
||||
color: #fff;
|
||||
text-align: left;
|
||||
padding: 5px;
|
||||
border-radius: 6px;
|
||||
|
||||
/* Position the tooltip text - see examples below! */
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* Show the tooltip text when you mouse over the tooltip container */
|
||||
.tooltip:hover .tooltiptext {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
/* Show the tooltip text when you mouse over the tooltip container */
|
||||
.tooltip:hover .tooltiptext {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
const path = require('path');
|
||||
const redhatDependencies = require('electron-installer-redhat/src/dependencies');
|
||||
|
||||
const linuxIconSet = {
|
||||
'16x16': 'appicons/icons/png/16x16.png',
|
||||
'24x24': 'appicons/icons/png/24x24.png',
|
||||
'32x32': 'appicons/icons/png/32x32.png',
|
||||
'48x48': 'appicons/icons/png/48x48.png',
|
||||
'64x64': 'appicons/icons/png/64x64.png',
|
||||
'128x128': 'appicons/icons/png/128x128.png',
|
||||
'256x256': 'appicons/icons/png/256x256.png',
|
||||
'512x512': 'appicons/icons/png/512x512.png',
|
||||
};
|
||||
|
||||
const linuxDesktopTemplate = path.resolve(__dirname, 'packaging/linux/trimsp.desktop.ejs');
|
||||
|
||||
// The upstream RPM maker assumes Fedora-style package names. Mageia provides
|
||||
// GTK 3 under lib64gtk+3_0, so allow either name in the generated Requires.
|
||||
redhatDependencies.dependencyMap.gtk3 = '(gtk3 or lib64gtk+3_0)';
|
||||
|
||||
module.exports = {
|
||||
packagerConfig: {
|
||||
icon: 'appicons/icons/png/1024x1024.png',
|
||||
extraResource: ['resources/bin'],
|
||||
ignore: [
|
||||
'Readme.md',
|
||||
'ToDo.txt',
|
||||
'TrimSP.cfg',
|
||||
'fortran/*',
|
||||
'\\.flatpak-builder($|/)',
|
||||
'\\.tmp-flatpak-manual($|/)',
|
||||
'out-flatpak-test($|/)',
|
||||
],
|
||||
},
|
||||
makers: [
|
||||
{
|
||||
name: '@electron-forge/maker-squirrel',
|
||||
config: {
|
||||
name: 'TrimSP',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '@electron-forge/maker-zip',
|
||||
platforms: ['darwin'],
|
||||
},
|
||||
{
|
||||
name: '@electron-forge/maker-deb',
|
||||
config: {
|
||||
name: 'trimsp',
|
||||
productName: 'TrimSP',
|
||||
genericName: 'Ion implantation simulator',
|
||||
description: 'TRIM.SP simulation GUI for ion implantation studies.',
|
||||
categories: ['Science'],
|
||||
icon: linuxIconSet,
|
||||
desktopTemplate: linuxDesktopTemplate,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '@electron-forge/maker-rpm',
|
||||
config: {
|
||||
name: 'trimsp',
|
||||
productName: 'TrimSP',
|
||||
genericName: 'Ion implantation simulator',
|
||||
description: 'TRIM.SP simulation GUI for ion implantation studies.',
|
||||
categories: ['Science'],
|
||||
icon: linuxIconSet,
|
||||
desktopTemplate: linuxDesktopTemplate,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '@electron-forge/maker-flatpak',
|
||||
config: {
|
||||
options: {
|
||||
id: 'ch.psi.lem.TrimSP',
|
||||
productName: 'TrimSP',
|
||||
genericName: 'Ion implantation simulator',
|
||||
description: 'TRIM.SP simulation GUI for ion implantation studies.',
|
||||
baseVersion: '24.08',
|
||||
runtimeVersion: '24.08',
|
||||
extraFlatpakBuilderArgs: ['--state-dir=.flatpak-builder'],
|
||||
icon: linuxIconSet,
|
||||
modules: [],
|
||||
categories: ['Science'],
|
||||
finishArgs: [
|
||||
'--share=ipc',
|
||||
'--share=network',
|
||||
'--socket=x11',
|
||||
'--socket=wayland',
|
||||
'--device=dri',
|
||||
'--filesystem=home',
|
||||
'--filesystem=/tmp',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
+1
-35
@@ -401,9 +401,7 @@ C LMAX is maximum number of layers and JMAX is maximum number of
|
||||
C elements per layer.
|
||||
JMAX=5
|
||||
|
||||
C This part reads the input file (new format).
|
||||
C The JavaScript/Electron frontend writes this sequential block layout,
|
||||
C so the READ order below must stay in sync with CreateInpFile().
|
||||
C This part reads the input file (new format)
|
||||
OPEN(UNIT=99,file=errnam,STATUS='replace')
|
||||
OPEN(UNIT=11,file=innam,STATUS='unknown',ERR=1359)
|
||||
C First line: properties of projectile
|
||||
@@ -816,9 +814,6 @@ C
|
||||
ENDDO
|
||||
C
|
||||
C PROJECTILE LOOP
|
||||
C Each pass transports one projectile history. The state vectors
|
||||
C X/Y/Z, E, direction cosines, current layer index, etc. are updated
|
||||
C in-place until the particle stops, backscatters or transmits.
|
||||
C
|
||||
1 CONTINUE
|
||||
NPROJ=NPROJ+1
|
||||
@@ -834,10 +829,6 @@ C
|
||||
KK1=KK0
|
||||
C
|
||||
C COLLISION LOOP (INCLUDES WEAK SIMULTANEOUS COLL. FOR KK1.LT.4)
|
||||
C KK controls the treatment of weak simultaneous collisions.
|
||||
C For every active projectile we choose a collision partner, sample an
|
||||
C impact parameter, solve the scattering geometry for the selected
|
||||
C interatomic potential and then update the projectile state.
|
||||
C
|
||||
DO 245 KK=KK1,0,-1
|
||||
C
|
||||
@@ -3383,10 +3374,6 @@ C & I0,3x))
|
||||
& ,1x))
|
||||
|
||||
inquire(FILE='fort.33',EXIST=FORT33)
|
||||
C fort.33 is the compact per-run summary consumed by the GUI for scan
|
||||
C plots (fractions stopped in each layer, backscattering, transmission,
|
||||
C mean depth, etc.). The header line is written once, then each run
|
||||
C appends a single summary row.
|
||||
if (.not.FORT33) then
|
||||
open(33)
|
||||
WRITE(33,7802) (chem(k),k=1,NLayers)
|
||||
@@ -3933,10 +3920,6 @@ C
|
||||
REAL*8 X1SY,X2SY,X3SY,X4SY,X5SY,X6SY,X1S,X2S,X3S,X4S,X5S,X6S,Y
|
||||
LOGICAL EQUAL
|
||||
|
||||
C Convert accumulated raw sums into per-particle moments by dividing
|
||||
C through the population size Y. The higher-level MOMENTS/MOMENTN
|
||||
C routines use these normalized values to build means, spreads and
|
||||
C uncertainties for the reported observables.
|
||||
IF(EQUAL(Y,0.D0))GOTO 10
|
||||
X1SY=X1S/Y
|
||||
X2SY=X2S/Y
|
||||
@@ -3954,9 +3937,6 @@ C uncertainties for the reported observables.
|
||||
& ,SPHI(N)
|
||||
REAL*8 SRAT,CX2,CY2,CZ2,UNIT
|
||||
|
||||
C Rotate the current direction cosines by the sampled scattering
|
||||
C angles (psi,phi). The output direction is explicitly renormalized
|
||||
C because repeated collisions amplify small floating-point drift.
|
||||
DO IV=1,N
|
||||
SRAT=SPSI(IV)/SINE(IV)
|
||||
CX2=CPSI(IV)*COSX(IV)+SPSI(IV)*SINE(IV)*CPHI(IV)
|
||||
@@ -3979,8 +3959,6 @@ C MAKE SURE COSZ.NE.0.
|
||||
INTEGER n,I
|
||||
C
|
||||
C FETCH A NEW VELOCITY FROM A MAXWELLIAN FLUX AT A SURFACE
|
||||
C Vectorized version used when multiple projectiles are initialized
|
||||
C together with thermal surface velocities.
|
||||
C
|
||||
REAL*8 FG(2*N),FFG(N),E(N),COSX(N),COSY(N),COSZ(N),SINE(N)
|
||||
C DIMENSIOM E(N),COSX(N),COSY(N),COSZ(N),SINE(N)
|
||||
@@ -4008,7 +3986,6 @@ C DIMENSIOM E(N),COSX(N),COSY(N),COSZ(N),SINE(N)
|
||||
SUBROUTINE VELOC(E,COSX,COSY,COSZ,SINE)
|
||||
C
|
||||
C FETCH A NEW VELOCITY FROM A MAXWELLIAN FLUX AT A SURFACE
|
||||
C Scalar version that reuses Gaussian deviates generated by FGAUSS.
|
||||
C
|
||||
IMPLICIT NONE
|
||||
INTEGER INIV1,INIV3
|
||||
@@ -4051,8 +4028,6 @@ C ZA=0.
|
||||
C ZS=1.
|
||||
C
|
||||
C IT IS THE BOX-MUELLER METHOD
|
||||
C FG returns symmetric normal deviates, while FFG stores the positive
|
||||
C half-space distribution used for Maxwellian flux sampling.
|
||||
C
|
||||
IMPLICIT NONE
|
||||
INTEGER IND,IND2,IANZ,JJ
|
||||
@@ -4228,9 +4203,6 @@ C why is it needed??
|
||||
INTEGER I,N,J,INC
|
||||
REAL*8 ARRAY(N),TARGT
|
||||
|
||||
C Return the first index whose value is strictly greater than TARGT.
|
||||
C This is used to map a continuous coordinate/depth onto the current
|
||||
C layer or histogram bin in monotonic arrays.
|
||||
J=1
|
||||
IF(INC.LT.0) J=N*(-INC)
|
||||
DO I=1,N
|
||||
@@ -4248,8 +4220,6 @@ C layer or histogram bin in monotonic arrays.
|
||||
REAL*8 p1,p2,p3,pi
|
||||
real*4 random(2)
|
||||
DATA pi/3.14159265358979D0/
|
||||
C Sample a Gaussian-distributed incident energy around E0 using a
|
||||
C Box-Mueller transform. Epar is the per-projectile starting energy.
|
||||
call ranlux(random, 2)
|
||||
p1 = Esig*DSQRT(-2.D0*DLOG(1.D0-DBLE(random(1))))
|
||||
p2 = 2.D0*pi*DBLE(random(2))
|
||||
@@ -4267,8 +4237,6 @@ C Box-Mueller transform. Epar is the per-projectile starting energy.
|
||||
REAL*8 p1,p2,p3,pi
|
||||
real*4 random(2)
|
||||
DATA pi/3.14159265358979D0/
|
||||
C Sample a Gaussian-distributed incidence angle around ALPHA and
|
||||
C return both the angle in radians (ALFA) and its sine/cosine.
|
||||
call ranlux(random, 2)
|
||||
p1 = ALPHASIG*DSQRT(-2.D0*DLOG(1.D0-DBLE(random(1))))
|
||||
p2 = 2.D0*pi*DBLE(random(2))
|
||||
@@ -4288,8 +4256,6 @@ C return both the angle in radians (ALFA) and its sine/cosine.
|
||||
REAL*8 F1,F2
|
||||
REAL*8 TINY
|
||||
PARAMETER (TINY = 1.0D-10)
|
||||
C Centralized floating-point comparison used throughout the transport
|
||||
C code to avoid exact equality checks on derived real-valued quantities.
|
||||
IF (DABS(F1-F2).LE.TINY) THEN
|
||||
EQUAL = .TRUE.
|
||||
ELSE
|
||||
|
||||
@@ -1,64 +1,9 @@
|
||||
const path = require('path');
|
||||
const { app, BrowserWindow, Menu, dialog, ipcMain, fs } = require('electron');
|
||||
|
||||
let currentWorkPath = process.cwd();
|
||||
|
||||
app.setName('TrimSP');
|
||||
|
||||
function showAboutDialog(parentWindow) {
|
||||
const detail = [
|
||||
'TRIM.SP simulation GUI for low-energy ion implantation studies.',
|
||||
`Version: ${app.getVersion()}`,
|
||||
'License: GNU General Public License v2 (GPL-2.0).',
|
||||
'Maintained by the Low Energy Muons group at the Paul Scherrer Institute.',
|
||||
'Main contributor: Zaher Salman.',
|
||||
'',
|
||||
'Key references:',
|
||||
'J. P. Biersack and W. Eckstein, Appl. Phys. A 34, 73-94 (1984).',
|
||||
'W. Eckstein, Computer Simulation of Ion-Solid Interactions (1991).',
|
||||
'E. Morenzoni et al., NIM B 192, 245-266 (2002).',
|
||||
'',
|
||||
'Project repositories:',
|
||||
'Bitbucket: bitbucket.org/zaher-salman/trimsp',
|
||||
'Gitea: gitea.psi.ch/LMU/TRIMSP'
|
||||
].join('\n');
|
||||
|
||||
dialog.showMessageBox(parentWindow, {
|
||||
type: 'info',
|
||||
title: 'About TrimSP',
|
||||
message: 'TrimSP',
|
||||
detail: detail,
|
||||
buttons: ['OK'],
|
||||
icon: parentWindow ? undefined : undefined
|
||||
});
|
||||
}
|
||||
|
||||
// Some Linux/remote desktop setups expose a broken GPU context to Electron.
|
||||
// Fall back to software rendering instead of crashing on startup.
|
||||
app.disableHardwareAcceleration();
|
||||
|
||||
if (process.platform === 'linux') {
|
||||
// The XDG portal dialog backend ignores defaultPath on some systems and
|
||||
// may cancel folder selection entirely in X11/SSH sessions.
|
||||
app.commandLine.appendSwitch('xdg-portal-required-version', '999');
|
||||
}
|
||||
|
||||
function getDefaultDialogPath() {
|
||||
return currentWorkPath || process.cwd();
|
||||
}
|
||||
|
||||
function getWindowIconPath() {
|
||||
if (app.isPackaged) {
|
||||
return path.join(process.resourcesPath, 'app.asar', 'icon.png');
|
||||
}
|
||||
return path.join(__dirname, 'icon.png');
|
||||
}
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 1000,
|
||||
height: 610,
|
||||
icon: getWindowIconPath(),
|
||||
width: 950,
|
||||
height: 580,
|
||||
icon: "/usr/lib/TrimSP/resources/app/icon.png",
|
||||
webPreferences: {
|
||||
contextIsolation: false,
|
||||
nodeIntegration: true,
|
||||
@@ -79,7 +24,7 @@ function createWindow () {
|
||||
click () {
|
||||
dialog.showOpenDialog(win,
|
||||
{ title : "Load configuration file",
|
||||
defaultPath : getDefaultDialogPath(),
|
||||
defaultPath : app.getPath('temp'),
|
||||
//buttonLabel : "Custom button",
|
||||
filters :[
|
||||
{name: 'Config file type', extensions: ['cfg']},
|
||||
@@ -100,12 +45,12 @@ function createWindow () {
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Save Folder...',
|
||||
label: 'Select Folder...',
|
||||
accelerator: 'CmdOrCtrl+F',
|
||||
click () {
|
||||
dialog.showOpenDialog(win,
|
||||
{ title: "Select folder",
|
||||
defaultPath : getDefaultDialogPath(),
|
||||
defaultPath : app.getPath('temp'),
|
||||
properties:["openDirectory"]}
|
||||
).then(result => {
|
||||
setImmediate(function() {
|
||||
@@ -134,16 +79,13 @@ function createWindow () {
|
||||
click () {
|
||||
dialog.showSaveDialog(win,
|
||||
{ title : "Save configuration file",
|
||||
defaultPath : path.join(getDefaultDialogPath(), 'TrimSP.cfg'),
|
||||
defaultPath : app.getPath('temp'),
|
||||
filters :[
|
||||
{name: 'Config file type', extensions: ['cfg']},
|
||||
{name: 'All Files', extensions: ['*']}
|
||||
],
|
||||
properties: ['showOverwriteConfirmation']}
|
||||
).then(result => {
|
||||
if (result.canceled || !result.filePath) {
|
||||
return;
|
||||
}
|
||||
setImmediate(function() {
|
||||
var focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
focusedWindow.webContents.send('saveFile',result.filePath);
|
||||
@@ -257,12 +199,18 @@ function createWindow () {
|
||||
{
|
||||
role: 'viewMenu'
|
||||
},
|
||||
{
|
||||
role: 'windowMenu'
|
||||
},
|
||||
{
|
||||
role: 'help',
|
||||
submenu: [
|
||||
{
|
||||
label: 'About TrimSP',
|
||||
click () { showAboutDialog(win); }
|
||||
role: 'about'
|
||||
},
|
||||
{
|
||||
label: 'Learn More',
|
||||
click () { require('electron').shell.openExternal('http://electron.atom.io') }
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -294,27 +242,19 @@ app.on('activate', () => {
|
||||
// Reply to calls from browser button
|
||||
ipcMain.on('browseFolder', (event, args) => {
|
||||
console.log('received a message: '+args);
|
||||
const senderWindow = BrowserWindow.fromWebContents(event.sender);
|
||||
dialog.showOpenDialog(senderWindow, { title: "Select folder",
|
||||
defaultPath : getDefaultDialogPath(),
|
||||
properties:["openDirectory"]}
|
||||
).then(result => {
|
||||
console.log(result)
|
||||
if (result.canceled || result.filePaths.length === 0) {
|
||||
event.reply('browseFolderFallback');
|
||||
return;
|
||||
}
|
||||
event.reply('browseFolder', result.filePaths);
|
||||
app.setPath('temp',result.filePaths[0]);
|
||||
}).catch(err => {
|
||||
console.log(err);
|
||||
})
|
||||
});
|
||||
|
||||
ipcMain.on('updateWorkPath', (event, folder) => {
|
||||
if (folder) {
|
||||
currentWorkPath = folder;
|
||||
}
|
||||
dialog.showOpenDialog({ title: "Select folder",
|
||||
defaultPath : app.getPath('temp'),
|
||||
properties:["openDirectory"]}
|
||||
).then(result => {
|
||||
console.log(result)
|
||||
setImmediate(function() {
|
||||
var focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
focusedWindow.webContents.send('browseFolder',result.filePaths);
|
||||
app.setPath('temp',result.filePaths[0]);
|
||||
});
|
||||
}).catch(err => {
|
||||
console.log(err);
|
||||
})
|
||||
});
|
||||
|
||||
//ipcMain.on('browseFolder-send', (event, args) => {
|
||||
|
||||
Generated
-6165
File diff suppressed because it is too large
Load Diff
+38
-9
@@ -1,16 +1,12 @@
|
||||
{
|
||||
"name": "TrimSP",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.2",
|
||||
"description": "Trim.SP simulation to calculate stopping profile of implanted probes.",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"start": "electron-forge start",
|
||||
"package": "electron-forge package",
|
||||
"make": "electron-forge make",
|
||||
"make:flatpak": "FORGE_FLATPAK=1 electron-forge make --targets=@electron-forge/maker-flatpak",
|
||||
"checksums:md5": "sh -c 'for d in out/make/deb/x64 out/make/rpm/x64 out/make/flatpak/x86_64; do [ -d \"$d\" ] || continue; for f in \"$d\"/*; do [ -f \"$f\" ] || continue; case \"$f\" in *.deb|*.rpm|*.flatpak) base=$(basename \"$f\"); (cd \"$d\" && md5sum \"$base\" > \"$base.md5\");; esac; done; done'",
|
||||
"checksums:sha256": "sh -c 'for d in out/make/deb/x64 out/make/rpm/x64 out/make/flatpak/x86_64; do [ -d \"$d\" ] || continue; for f in \"$d\"/*; do [ -f \"$f\" ] || continue; case \"$f\" in *.deb|*.rpm|*.flatpak) base=$(basename \"$f\"); (cd \"$d\" && sha256sum \"$base\" > \"$base.sha256\");; esac; done; done'",
|
||||
"checksums": "npm run checksums:md5 && npm run checksums:sha256"
|
||||
"make": "electron-forge make"
|
||||
},
|
||||
"keywords": [
|
||||
"TRIM",
|
||||
@@ -21,14 +17,47 @@
|
||||
"devDependencies": {
|
||||
"@electron-forge/cli": "^6.0.0-beta.57",
|
||||
"@electron-forge/maker-deb": "^6.0.0-beta.57",
|
||||
"@electron-forge/maker-flatpak": "^7.11.1",
|
||||
"@electron-forge/maker-rpm": "^6.0.0-beta.57",
|
||||
"@electron-forge/maker-squirrel": "^6.0.0-beta.57",
|
||||
"@electron-forge/maker-zip": "^6.0.0-beta.57",
|
||||
"electron": "40.6.0"
|
||||
"electron": "^11.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"plotly.js-dist": "^1.58.4"
|
||||
},
|
||||
"config": {}
|
||||
"config": {
|
||||
"forge": {
|
||||
"packagerConfig": {
|
||||
"icon": "appicons/icons/png/1024x1024.png",
|
||||
"ignore": [
|
||||
"Readme.md",
|
||||
"ToDo.txt",
|
||||
"TrimSP.cfg",
|
||||
"fortran/*"
|
||||
]
|
||||
},
|
||||
"makers": [
|
||||
{
|
||||
"name": "@electron-forge/maker-squirrel",
|
||||
"config": {
|
||||
"name": "TrimSP"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "@electron-forge/maker-zip",
|
||||
"platforms": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "@electron-forge/maker-deb",
|
||||
"config": {}
|
||||
},
|
||||
{
|
||||
"name": "@electron-forge/maker-rpm",
|
||||
"config": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Name=<%= productName %>
|
||||
<% if (description) { print(`Comment=${description}\n`) } %>GenericName=<%= genericName %>
|
||||
Exec=<%= name %> %U<% if (execArguments && execArguments.length) { %> <%= execArguments.join(' ') %><% } %>
|
||||
Icon=<%= name %>
|
||||
Type=Application
|
||||
StartupNotify=true
|
||||
StartupWMClass=TrimSP
|
||||
Categories=<%= categories.join(';') %>;
|
||||
<% if (mimeType && mimeType.length) { %>MimeType=<%= mimeType.join(';') %>;<% } %>
|
||||
Binary file not shown.
Reference in New Issue
Block a user