Skip to content

Commit 3ddc09a

Browse files
committed
Add new icon files for Nebulae project
- Added PNG icon for model in `src/main/resources/nebulae_icons/model/icon.png` - Added ICO icon for script in `src/main/resources/nebulae_icons/script/icon.ico` - Added PNG icon for script in `src/main/resources/nebulae_icons/script/icon.png`
1 parent cf6a704 commit 3ddc09a

27 files changed

Lines changed: 174 additions & 136 deletions

src/main/java/niwer/nebulae/NebulaeEngine.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,6 @@ public class NebulaeEngine {
4343
* @return An instance of the requested NebulaeProcessor.
4444
*/
4545
public static NebulaeProcessor forVersion(NebulaeVersion version, byte[] key) { return version.getProcessor(key); }
46+
47+
4648
}

src/main/java/niwer/nebulae/NebulaeFormat.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ public class NebulaeFormat {
1717
public static final byte TYPE_SCRIPT = 0x05; // For script files (e.g. Lua or JavaScript)
1818
public static final byte TYPE_FONT = 0x06; // For font files (e.g. TTF/OTF)
1919
public static final byte TYPE_DATA = 0x07; // For generic data files (e.g. JSON, binary blobs)
20+
public static final byte TYPE_ARCHIVE = 0x08; // For archive files (e.g. ZIP, RAR)
2021
}

src/main/java/niwer/nebulae/NebulaeIcons.java

Lines changed: 0 additions & 105 deletions
This file was deleted.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package niwer.nebulae.icons;
2+
3+
import java.io.IOException;
4+
import java.nio.file.Files;
5+
import java.nio.file.Path;
6+
import java.nio.file.Paths;
7+
import java.nio.file.StandardCopyOption;
8+
9+
public abstract class AbstractFileIconHandler implements FileIconHandler {
10+
11+
private static final Path ICON_DIRECTORY = Paths.get(System.getProperty("user.home"), ".nebulae_register", "icons");
12+
13+
protected Path saveIcon(String fileType, NebulaeIcons icon, String extension) throws IOException {
14+
Files.createDirectories(ICON_DIRECTORY);
15+
16+
Path iconPath = ICON_DIRECTORY.resolve(fileType + extension);
17+
Files.copy(icon.asStream(), iconPath, StandardCopyOption.REPLACE_EXISTING);
18+
return iconPath;
19+
}
20+
21+
protected void run(String... command) throws IOException, InterruptedException {
22+
if (new ProcessBuilder(command).inheritIO().start().waitFor() != 0) throw new IOException("Command failed: " + String.join(" ", command));
23+
}
24+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package niwer.nebulae.icons;
2+
3+
public interface FileIconHandler {
4+
5+
void registerFileIcon(String extension, String fileType, String description, NebulaeIcons iconStream) throws Exception;
6+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package niwer.nebulae.icons;
2+
3+
import java.util.Locale;
4+
5+
public final class FileIconRegistryManager {
6+
7+
private static final FileIconHandler HANDLER = createHandler();
8+
9+
private FileIconRegistryManager() {}
10+
11+
private static FileIconHandler createHandler() {
12+
String os = System.getProperty("os.name").toLowerCase(Locale.ROOT).trim();
13+
if (os.contains("win")) return new WindowsFileIconHandler();
14+
if (os.contains("linux")) return new LinuxFileIconHandler();
15+
if (os.contains("mac")) return new MacOSFileIconHandler();
16+
throw new UnsupportedOperationException("Unsupported OS: " + os);
17+
}
18+
19+
/**
20+
* Registers a custom file icon for the given extension. The file type will be "niwer.nebulae.[extension]", and the description will be the one provided by the icon.
21+
*
22+
* @param extension The file extension, including the dot (e.g. ".txt")
23+
* @param icon The icon to use for this file type
24+
* @throws Exception if an error occurs while registering the icon (e.g. insufficient permissions, unsupported OS, etc.)
25+
*/
26+
public static void register(String extension, NebulaeIcons icon) throws Exception {
27+
HANDLER.registerFileIcon(extension, "niwer.nebulae." + extension.replace(".", ""), icon.description(), icon);
28+
}
29+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package niwer.nebulae.icons;
2+
3+
import java.nio.file.Files;
4+
import java.nio.file.Path;
5+
import java.nio.file.Paths;
6+
import java.nio.file.StandardCopyOption;
7+
8+
/**
9+
* This should support most Linux desktop environments that follow the XDG standard, but may not work on all distributions or setups.
10+
*/
11+
public final class LinuxFileIconHandler extends AbstractFileIconHandler {
12+
13+
@Override
14+
public void registerFileIcon(String extension, String fileType, String description, NebulaeIcons icon) throws Exception {
15+
Path iconPath = saveIcon(fileType, icon, ".png");
16+
17+
Path mimeDir = Paths.get(System.getProperty("user.home"), ".local/share/mime/packages");
18+
Files.createDirectories(mimeDir);
19+
20+
String mime = "application/x-" + fileType.toLowerCase();
21+
Path xml = mimeDir.resolve(fileType + ".xml");
22+
Files.writeString(xml, """
23+
<?xml version="1.0" encoding="UTF-8"?>
24+
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
25+
<mime-type type='%s'>
26+
<comment>%s</comment>
27+
<glob pattern='*%s'/>
28+
</mime-type>
29+
</mime-info>
30+
""".formatted(mime, description, extension));
31+
32+
run("update-mime-database", System.getProperty("user.home") + "/.local/share/mime");
33+
34+
Path iconDir = Paths.get(System.getProperty("user.home"), ".local/share/icons/hicolor/256x256/mimetypes");
35+
Files.createDirectories(iconDir);
36+
Files.copy(iconPath, iconDir.resolve(mime.replace("/", "-") + ".png"), StandardCopyOption.REPLACE_EXISTING);
37+
}
38+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package niwer.nebulae.icons;
2+
3+
public final class MacOSFileIconHandler extends AbstractFileIconHandler {
4+
5+
@Override
6+
public void registerFileIcon(String extension, String fileType, String description, NebulaeIcons icon) {
7+
throw new UnsupportedOperationException("Custom file icons are not supported on macOS.");
8+
}
9+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package niwer.nebulae.icons;
2+
3+
import java.io.InputStream;
4+
import java.util.Locale;
5+
6+
import niwer.nebulae.NebulaeFormat;
7+
8+
public enum NebulaeIcons {
9+
10+
DEFAULT("data", NebulaeFormat.TYPE_DATA, "Default"), // Default icon for unregistered file types
11+
12+
MODEL("model", NebulaeFormat.TYPE_MODEL, "Model"),
13+
IMAGE("image", NebulaeFormat.TYPE_IMAGE, "Image"),
14+
ANIMATION("animation", NebulaeFormat.TYPE_ANIMATION, "Animation"),
15+
AUDIO("audio", NebulaeFormat.TYPE_SOUND, "Audio"),
16+
SCRIPT("script", NebulaeFormat.TYPE_SCRIPT, "Script"),
17+
FONT("font", NebulaeFormat.TYPE_FONT, "Font"),
18+
DATA("data", NebulaeFormat.TYPE_DATA, "Data"),
19+
ARCHIVE("archive", NebulaeFormat.TYPE_ARCHIVE, "Archive");
20+
21+
private final String SUB_FOLDER_PATH;
22+
public final String DESCRIPTION;
23+
24+
private InputStream stream;
25+
26+
NebulaeIcons(String path, byte formatType, String description) {
27+
this.SUB_FOLDER_PATH = path;
28+
this.DESCRIPTION = description;
29+
}
30+
31+
public String description() { return DESCRIPTION; }
32+
33+
public InputStream asStream() {
34+
if (stream == null) {
35+
final String OS = System.getProperty("os.name").toLowerCase(Locale.ROOT).trim();
36+
final String EXTENSION = OS.contains("win") ? ".ico" : ".png";
37+
38+
/* Try getting the icon inside the JAR */
39+
stream = getClass().getResourceAsStream("/nebulae_icons/" + SUB_FOLDER_PATH + "/icon" + EXTENSION);
40+
if (stream == null) throw new RuntimeException("Icon not found: " + SUB_FOLDER_PATH);
41+
}
42+
return stream;
43+
}
44+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package niwer.nebulae.icons;
2+
3+
import java.io.IOException;
4+
import java.nio.file.Path;
5+
6+
public final class WindowsFileIconHandler extends AbstractFileIconHandler {
7+
8+
@Override
9+
public void registerFileIcon(String extension, String fileType, String description, NebulaeIcons icon) throws Exception {
10+
Path iconPath = saveIcon(fileType, icon, ".ico");
11+
run("reg", "add", "HKCU\\Software\\Classes\\" + extension, "/ve", "/d", fileType, "/f");
12+
run("reg", "add", "HKCU\\Software\\Classes\\" + fileType, "/ve", "/d", description, "/f");
13+
run("reg", "add", "HKCU\\Software\\Classes\\" + fileType + "\\DefaultIcon", "/ve", "/d", iconPath.toString(), "/f");
14+
refreshExplorer();
15+
}
16+
17+
private void refreshExplorer() throws IOException, InterruptedException {
18+
run("taskkill", "/f", "/im", "explorer.exe");
19+
new ProcessBuilder("cmd", "/c", "start", "explorer").start();
20+
}
21+
}

0 commit comments

Comments
 (0)