Modernize application icon
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 102 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 509 B After Width: | Height: | Size: 761 B |
|
Before Width: | Height: | Size: 772 B After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 353 KiB After Width: | Height: | Size: 364 KiB |
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" role="img" aria-labelledby="title description">
|
||||
<title id="title">TRIMSP-NL Workbench icon</title>
|
||||
<desc id="description">An orange particle trajectory stopping as a spin-polarized muon inside a layered teal target.</desc>
|
||||
<defs>
|
||||
<linearGradient id="background" x1="140" y1="80" x2="880" y2="960" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#214b56"/>
|
||||
<stop offset="1" stop-color="#102f38"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="trajectory" x1="110" y1="130" x2="456" y2="686" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#e58454"/>
|
||||
<stop offset="1" stop-color="#bd5f37"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="stopPoint" cx="42%" cy="35%" r="65%">
|
||||
<stop offset="0" stop-color="#fff9df"/>
|
||||
<stop offset="0.45" stop-color="#f4d48a"/>
|
||||
<stop offset="1" stop-color="#d27a43"/>
|
||||
</radialGradient>
|
||||
<clipPath id="tile">
|
||||
<rect x="48" y="48" width="928" height="928" rx="208"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
|
||||
<g>
|
||||
<rect x="48" y="48" width="928" height="928" rx="208" fill="url(#background)"/>
|
||||
<g clip-path="url(#tile)">
|
||||
<!-- Three target layers remain distinct even at taskbar icon sizes. -->
|
||||
<path d="M48 444 C276 405 503 483 976 420 V622 H48 Z" fill="#f2ead8"/>
|
||||
<path d="M48 596 C332 553 615 660 976 578 V802 H48 Z" fill="#75aeb4"/>
|
||||
<path d="M48 774 C322 730 647 842 976 747 V976 H48 Z" fill="#376a70"/>
|
||||
<path d="M48 444 C276 405 503 483 976 420" fill="none" stroke="#fff9ec" stroke-opacity="0.72" stroke-width="12"/>
|
||||
<path d="M48 596 C332 553 615 660 976 578" fill="none" stroke="#315f68" stroke-opacity="0.42" stroke-width="10"/>
|
||||
<path d="M48 774 C322 730 647 842 976 747" fill="none" stroke="#173943" stroke-opacity="0.55" stroke-width="10"/>
|
||||
|
||||
<!-- The trajectory preserves the physical idea of implantation and stopping. -->
|
||||
<path d="M190 160 C414 181 725 232 764 380 C799 520 589 546 463 667"
|
||||
fill="none" stroke="#7d321c" stroke-opacity="0.28" stroke-width="70"
|
||||
stroke-linecap="round" transform="translate(0 14)"/>
|
||||
<path d="M190 160 C414 181 725 232 764 380 C799 520 589 546 463 667"
|
||||
fill="none" stroke="url(#trajectory)" stroke-width="70" stroke-linecap="round"/>
|
||||
<!-- The spin axis passes behind the implanted muon. -->
|
||||
<path d="M355 762 L545 572" fill="none" stroke="#fff6d6" stroke-width="40" stroke-linecap="round"/>
|
||||
<path d="M355 762 L545 572" fill="none" stroke="#173943" stroke-width="22" stroke-linecap="round"/>
|
||||
<path d="M570 547 L553 600 L517 564 Z" fill="#173943" stroke="#fff6d6" stroke-width="9" stroke-linejoin="round"/>
|
||||
<circle cx="450" cy="681" r="77" fill="#0d2931" fill-opacity="0.24"/>
|
||||
<circle cx="450" cy="667" r="60" fill="url(#stopPoint)" stroke="#fff6d6" stroke-width="10"/>
|
||||
</g>
|
||||
<rect x="54" y="54" width="916" height="916" rx="202" fill="none" stroke="#eaf2ee" stroke-opacity="0.24" stroke-width="12"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 102 KiB |
@@ -1,12 +1,50 @@
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const { app, BrowserWindow, Menu, dialog, ipcMain } = require('electron');
|
||||
const { spawnSync } = require('child_process');
|
||||
const { app, BrowserWindow, Menu, dialog, ipcMain, nativeImage } = require('electron');
|
||||
|
||||
let currentWorkPath = process.cwd();
|
||||
const startupOptions = parseStartupOptions(process.argv);
|
||||
|
||||
// Keep the internal Linux window class stable for existing desktop launchers.
|
||||
app.setName('TrimSP');
|
||||
// Packaged builds retain the class expected by installed desktop launchers.
|
||||
// A distinct development class prevents npm start from inheriting the icon
|
||||
// cached for an older system installation of TrimSP.
|
||||
app.setName(app.isPackaged ? 'TrimSP' : 'TrimSPDev');
|
||||
if (process.platform === 'linux' && !app.isPackaged) {
|
||||
// KDE resolves taskbar icons through matching desktop entries and ignores
|
||||
// Electron's development-window icon. Keep a hidden per-user entry tied
|
||||
// to this checkout so npm start uses the current repository artwork.
|
||||
try {
|
||||
const dataHome = process.env.XDG_DATA_HOME || path.join(app.getPath('home'), '.local', 'share');
|
||||
const applicationsDir = path.join(dataHome, 'applications');
|
||||
const desktopFile = path.join(applicationsDir, 'trimsp-dev.desktop');
|
||||
const executable = process.execPath.replace(/"/g, '\\"');
|
||||
const projectPath = __dirname.replace(/"/g, '\\"');
|
||||
const iconPath = path.join(__dirname, 'icon.png');
|
||||
const desktopContent = [
|
||||
'[Desktop Entry]',
|
||||
'Type=Application',
|
||||
'Name=TRIMSP-NL Workbench (Development)',
|
||||
`Exec="${executable}" "${projectPath}"`,
|
||||
`Icon=${iconPath}`,
|
||||
`X-TrimSP-Icon-MTime=${fs.statSync(iconPath).mtimeMs}`,
|
||||
'StartupWMClass=TrimSPDev',
|
||||
'NoDisplay=true',
|
||||
'Categories=Science;',
|
||||
'',
|
||||
].join('\n');
|
||||
fs.mkdirSync(applicationsDir, {recursive: true});
|
||||
if (!fs.existsSync(desktopFile) || fs.readFileSync(desktopFile, 'utf8') !== desktopContent) {
|
||||
fs.writeFileSync(desktopFile, desktopContent, 'utf8');
|
||||
// KDE caches desktop identities and icons; refresh that user cache only
|
||||
// when this entry changes. Other desktops safely ignore ENOENT here.
|
||||
spawnSync('kbuildsycoca6', ['--noincremental'], {stdio: 'ignore'});
|
||||
}
|
||||
app.setDesktopName('trimsp-dev.desktop');
|
||||
} catch (error) {
|
||||
console.warn('Could not register the development desktop entry:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function parseStartupOptions(argv) {
|
||||
const options = {
|
||||
@@ -152,10 +190,11 @@ function getWindowIconPath() {
|
||||
}
|
||||
|
||||
function createWindow () {
|
||||
const windowIcon = nativeImage.createFromPath(getWindowIconPath());
|
||||
const win = new BrowserWindow({
|
||||
width: 1000,
|
||||
height: 610,
|
||||
icon: getWindowIconPath(),
|
||||
icon: windowIcon,
|
||||
webPreferences: {
|
||||
contextIsolation: false,
|
||||
nodeIntegration: true,
|
||||
@@ -164,6 +203,13 @@ function createWindow () {
|
||||
}
|
||||
})
|
||||
|
||||
// Pass a native image explicitly for Linux panels that can use the window
|
||||
// icon directly. KDE resolves the development icon through the matching
|
||||
// desktop entry registered above.
|
||||
if (process.platform === 'linux' && !windowIcon.isEmpty()) {
|
||||
win.setIcon(windowIcon);
|
||||
}
|
||||
|
||||
let template = [
|
||||
{
|
||||
label: 'File',
|
||||
|
||||