Skip to content

[IDE] Add support for user-defined theme in sketchbook folder #7115

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions app/src/processing/app/EditorTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
import java.nio.file.Path;
import java.io.File;

import org.apache.commons.lang3.StringUtils;
import org.fife.ui.autocomplete.AutoCompletion;
import org.fife.ui.autocomplete.DefaultCompletionProvider;
import org.fife.ui.rsyntaxtextarea.RSyntaxDocument;
Expand Down Expand Up @@ -345,6 +346,20 @@ public void applyPreferences() {
}
// apply changes to the font size for the editor
Font editorFont = scale(PreferencesData.getFont("editor.font"));

// check whether a theme-defined editor font is available
Font themeFont = Theme.getFont("editor.font");
if (themeFont != null)
{
// Apply theme font if the editor font has *not* been changed by the user,
// This allows themes to specify an editor font which will only be applied
// if the user hasn't already changed their editor font via preferences.txt
String defaultFontName = StringUtils.defaultIfEmpty(PreferencesData.getDefault("editor.font"), "").split(",")[0];
if (defaultFontName.equals(editorFont.getName())) {
editorFont = new Font(themeFont.getName(), themeFont.getStyle(), editorFont.getSize());
}
}

textarea.setFont(editorFont);
scrollPane.getGutter().setLineNumberFont(editorFont);
}
Expand Down
54 changes: 45 additions & 9 deletions app/src/processing/app/Theme.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@
* and to make way for future ability to customize.
*/
public class Theme {

static final String THEME_DIR = "theme/";

/**
* Copy of the defaults in case the user mangles a preference.
Expand All @@ -73,7 +75,8 @@ public class Theme {

static protected void init() {
try {
table.load(new File(BaseNoGui.getContentFile("lib"), "theme/theme.txt"));
table.load(new File(BaseNoGui.getContentFile("lib"), THEME_DIR + "theme.txt"));
table.load(getThemeFile(THEME_DIR + "theme.txt"));
} catch (Exception te) {
Base.showError(null, tr("Could not read color theme settings.\n"
+ "You'll need to reinstall Arduino."),
Expand Down Expand Up @@ -177,6 +180,9 @@ static public Font getFont(String attr) {
String value = getDefault(attr);
set(attr, value);
font = PreferencesHelper.getFont(table, attr);
if (font == null) {
return null;
}
}
return font.deriveFont((float) scale(font.getSize()));
}
Expand Down Expand Up @@ -245,11 +251,10 @@ public static Map<String, Object> getStyledFont(String what, Font font) {
*/
static public Image getLibImage(String filename, Component who, int width,
int height) {
File libFolder = BaseNoGui.getContentFile("lib");
Image image = null;

// Use vector image when available
File vectorFile = new File(libFolder, filename + ".svg");
File vectorFile = getThemeFile(filename + ".svg");
if (vectorFile.exists()) {
try {
image = imageFromSVG(vectorFile.toURI().toURL(), width, height);
Expand All @@ -259,13 +264,16 @@ static public Image getLibImage(String filename, Component who, int width,
}
}

// Otherwise fall-back to PNG bitmaps
if (image == null) {
File bitmapFile = new File(libFolder, filename + ".png");
File bitmap2xFile = new File(libFolder, filename + "@2x.png");
File bitmapFile = getThemeFile(filename + ".png");

// Otherwise fall-back to PNG bitmaps, allowing user-defined bitmaps to
// override built-in svgs
if (image == null || (!isUserThemeFile(vectorFile) && isUserThemeFile(bitmapFile))) {
File bitmap2xFile = getThemeFile(filename + "@2x.png");

File imageFile;
if ((getScale() > 125 && bitmap2xFile.exists()) || !bitmapFile.exists()) {
if (((getScale() > 125 && bitmap2xFile.exists()) || !bitmapFile.exists())
&& isUserThemeFile(bitmapFile) == isUserThemeFile(bitmap2xFile)) {
imageFile = bitmap2xFile;
} else {
imageFile = bitmapFile;
Expand Down Expand Up @@ -298,7 +306,7 @@ static public Image getLibImage(String filename, Component who, int width,
*/
static public Image getThemeImage(String name, Component who, int width,
int height) {
return getLibImage("theme/" + name, who, width, height);
return getLibImage(THEME_DIR + name, who, width, height);
}

private static Image imageFromSVG(URL url, int width, int height)
Expand All @@ -324,5 +332,33 @@ static public Graphics2D setupGraphics2D(Graphics graphics) {
}
return g;
}

/**
* Check whether the specified file is a user-defined theme file
*/
static public boolean isUserThemeFile(File file) {
return file.exists() && file.getAbsolutePath().startsWith(BaseNoGui.getSketchbookFolder().getAbsolutePath());
}

/**
* @param name
* @return
*/
static public File getThemeFile(String name) {
File sketchBookThemeFolder = new File(BaseNoGui.getSketchbookFolder(), THEME_DIR);

File themeFile = new File(sketchBookThemeFolder, name);
if (themeFile.exists()) {
return themeFile;
}

if (name.startsWith(THEME_DIR)) {
themeFile = new File(sketchBookThemeFolder, name.substring(THEME_DIR.length()));
if (themeFile.exists()) {
return themeFile;
}
}

return new File(BaseNoGui.getContentFile("lib"), name);
}
}
4 changes: 2 additions & 2 deletions app/src/processing/app/forms/PasswordAuthorizationDialog.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package processing.app.forms;

import processing.app.Base;
import processing.app.Theme;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.WindowEvent;
import java.io.File;

import static processing.app.I18n.tr;

Expand Down Expand Up @@ -34,7 +34,7 @@ public PasswordAuthorizationDialog(Frame parent, String dialogText) {

typePasswordLabel.setText(dialogText);

icon.setIcon(new ImageIcon(new File(Base.getContentFile("lib"), "theme/lock.png").getAbsolutePath()));
icon.setIcon(new ImageIcon(Theme.getThemeFile("theme/lock.png").getAbsolutePath()));

passwordLabel.setText(tr("Password:"));

Expand Down
2 changes: 1 addition & 1 deletion app/src/processing/app/syntax/SketchTextArea.java
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ private void installFeatures() throws IOException {
private void setTheme(String name) throws IOException {
FileInputStream defaultXmlInputStream = null;
try {
defaultXmlInputStream = new FileInputStream(new File(BaseNoGui.getContentFile("lib"), "theme/syntax/" + name + ".xml"));
defaultXmlInputStream = new FileInputStream(processing.app.Theme.getThemeFile("theme/syntax/" + name + ".xml"));
Theme theme = Theme.load(defaultXmlInputStream);
theme.apply(this);
} finally {
Expand Down