From 6cd2e7c3566f6fa1a3c4ff313ad803b57bcb8d08 Mon Sep 17 00:00:00 2001
From: Ricardo JL Rufino <ricardo.jl.rufino@gmail.com>
Date: Wed, 13 May 2020 17:01:47 -0300
Subject: [PATCH 1/5] Allow install Theme from Preferences dialog

---
 .../arduino/view/preferences/Preferences.java | 53 +++++++++++++++++++
 app/src/processing/app/Theme.java             | 32 +++++++++++
 2 files changed, 85 insertions(+)

diff --git a/app/src/cc/arduino/view/preferences/Preferences.java b/app/src/cc/arduino/view/preferences/Preferences.java
index 005d2f83e54..d9ac14f29e2 100644
--- a/app/src/cc/arduino/view/preferences/Preferences.java
+++ b/app/src/cc/arduino/view/preferences/Preferences.java
@@ -40,16 +40,22 @@
 import processing.app.Theme;
 import processing.app.Theme.ZippedTheme;
 import processing.app.helpers.FileUtils;
+import processing.app.javax.swing.filechooser.FileNameExtensionFilter;
 import processing.app.legacy.PApplet;
 
 import javax.swing.*;
 import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
 import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
 import java.awt.event.WindowEvent;
 import java.io.File;
+import java.io.IOException;
 import java.util.Collection;
 import java.util.LinkedList;
 
+import static processing.app.I18n.format;
 import static processing.app.I18n.tr;
 
 public class Preferences extends javax.swing.JDialog {
@@ -869,6 +875,22 @@ private void showPreferencesData() {
         comboTheme.setSelectedItem(theme);
       }
     }
+    
+    // Allow install new themes.
+    String installItem = "-- " + tr( "Install from Zip" + " --");
+    comboTheme.addItem(installItem);
+    
+    comboTheme.addActionListener(new ActionListener() {
+      
+      @Override
+      public void actionPerformed(ActionEvent e) {
+        Object item = comboTheme.getSelectedItem();
+        if (item != null && item.toString().startsWith(installItem)) {
+          SwingUtilities.invokeLater(() -> comboTheme.getUI().setPopupVisible(comboTheme, false));
+          handleInstallTheme();
+        }
+      }
+    });
 
     Font editorFont = PreferencesData.getFont("editor.font");
     fontSizeField.setText(String.valueOf(editorFont.getSize()));
@@ -975,4 +997,35 @@ private void disableAllProxyFields() {
     autoProxyFieldsSetEnabled(false);
     manualProxyFieldsSetEnabled(false);
   }
+  
+  
+  public void handleInstallTheme() {
+    
+    JFileChooser fileChooser = new JFileChooser(System.getProperty("user.home"));
+    fileChooser.setDialogTitle(tr("Select a zip file containing the theme you'd like to add"));
+    fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
+    fileChooser.setFileFilter(new FileNameExtensionFilter(tr("ZIP files"), "zip"));
+
+    Dimension preferredSize = fileChooser.getPreferredSize();
+    fileChooser.setPreferredSize(new Dimension(preferredSize.width + 200, preferredSize.height + 200));
+
+    int returnVal = fileChooser.showOpenDialog(this);
+
+    if (returnVal != JFileChooser.APPROVE_OPTION) {
+      return;
+    }
+
+    File sourceFile = fileChooser.getSelectedFile();
+    
+    if (!sourceFile.isDirectory()) {
+      try {
+        
+        Theme.install(sourceFile);
+        
+      } catch (IOException e) {
+        base.getActiveEditor().statusError(e);
+        return;
+      }
+    }
+  }
 }
diff --git a/app/src/processing/app/Theme.java b/app/src/processing/app/Theme.java
index d38875b3597..eb0941bd884 100644
--- a/app/src/processing/app/Theme.java
+++ b/app/src/processing/app/Theme.java
@@ -47,6 +47,8 @@
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -66,6 +68,9 @@
 import org.apache.batik.transcoder.image.PNGTranscoder;
 import org.apache.commons.compress.utils.IOUtils;
 import org.apache.commons.lang3.StringUtils;
+
+import processing.app.Theme.ZippedTheme;
+import processing.app.helpers.FileUtils;
 import processing.app.helpers.OSUtils;
 import processing.app.helpers.PreferencesHelper;
 import processing.app.helpers.PreferencesMap;
@@ -724,4 +729,31 @@ static URL getUrl(ZipEntry entry) {
       return null;
     }
   }
+  
+  /**
+   * Intalll theme in skecthboot 
+   * @param zipTheme
+   */
+  static public void install(File zipTheme) throws IOException{
+    
+    // Validate...
+    ZippedTheme theme = ZippedTheme.load(NAMESPACE_USER, zipTheme);
+    
+    if(theme == null) {
+      throw new IOException(format(tr("Error loading theme: {0}"), zipTheme.getAbsolutePath()));
+    }
+    
+    // Create themes folder.
+    File themesFolder = new File(PreferencesData.get("sketchbook.path"), "theme");
+    if (!themesFolder.exists()) {
+      themesFolder.mkdir();
+    }
+    
+    // Copy
+    File dest = new File(themesFolder, zipTheme.getName());
+    Files.copy(zipTheme.toPath(), dest.toPath(),StandardCopyOption.REPLACE_EXISTING);
+    
+    System.out.println("COPY done: " + dest.getAbsolutePath());
+    
+  }
 }

From 4007b8470d14b009954ee85ff1dabbc97bda3fcd Mon Sep 17 00:00:00 2001
From: Ricardo JL Rufino <ricardo.jl.rufino@gmail.com>
Date: Wed, 13 May 2020 17:15:40 -0300
Subject: [PATCH 2/5] handle invalid themes

---
 app/src/cc/arduino/view/preferences/Preferences.java | 7 ++++++-
 app/src/processing/app/Theme.java                    | 5 ++---
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/app/src/cc/arduino/view/preferences/Preferences.java b/app/src/cc/arduino/view/preferences/Preferences.java
index d9ac14f29e2..789cb8dd654 100644
--- a/app/src/cc/arduino/view/preferences/Preferences.java
+++ b/app/src/cc/arduino/view/preferences/Preferences.java
@@ -1020,7 +1020,12 @@ public void handleInstallTheme() {
     if (!sourceFile.isDirectory()) {
       try {
         
-        Theme.install(sourceFile);
+        ZippedTheme theme = Theme.install(sourceFile);
+        
+        if(theme != null) {
+          comboTheme.addItem(theme);
+          comboTheme.setSelectedItem(theme);
+        }
         
       } catch (IOException e) {
         base.getActiveEditor().statusError(e);
diff --git a/app/src/processing/app/Theme.java b/app/src/processing/app/Theme.java
index eb0941bd884..9cbba7ef30a 100644
--- a/app/src/processing/app/Theme.java
+++ b/app/src/processing/app/Theme.java
@@ -734,7 +734,7 @@ static URL getUrl(ZipEntry entry) {
    * Intalll theme in skecthboot 
    * @param zipTheme
    */
-  static public void install(File zipTheme) throws IOException{
+  static public ZippedTheme install(File zipTheme) throws IOException{
     
     // Validate...
     ZippedTheme theme = ZippedTheme.load(NAMESPACE_USER, zipTheme);
@@ -753,7 +753,6 @@ static public void install(File zipTheme) throws IOException{
     File dest = new File(themesFolder, zipTheme.getName());
     Files.copy(zipTheme.toPath(), dest.toPath(),StandardCopyOption.REPLACE_EXISTING);
     
-    System.out.println("COPY done: " + dest.getAbsolutePath());
-    
+    return theme;
   }
 }

From c906806a4727afee376bfb6cee700566283a42c2 Mon Sep 17 00:00:00 2001
From: Ricardo JL Rufino <ricardo.jl.rufino@gmail.com>
Date: Wed, 13 May 2020 21:39:52 -0300
Subject: [PATCH 3/5] Avoid error on save, if canceled theme instalation

---
 app/src/cc/arduino/view/preferences/Preferences.java | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/app/src/cc/arduino/view/preferences/Preferences.java b/app/src/cc/arduino/view/preferences/Preferences.java
index 789cb8dd654..8ae8a805986 100644
--- a/app/src/cc/arduino/view/preferences/Preferences.java
+++ b/app/src/cc/arduino/view/preferences/Preferences.java
@@ -798,7 +798,10 @@ private void savePreferencesData() {
     if (comboTheme.getSelectedIndex() == 0) {
       PreferencesData.set("theme.file", "");
     } else {
-      PreferencesData.set("theme.file", ((ZippedTheme) comboTheme.getSelectedItem()).getKey());
+      Object selectedItem = comboTheme.getSelectedItem();
+      if(selectedItem instanceof ZippedTheme) {
+        PreferencesData.set("theme.file", ((ZippedTheme) selectedItem).getKey());
+      }
     }
 
     String newSizeText = fontSizeField.getText();

From 0ec01c38cc97468d7bde42ad66cd19a79c34c9fc Mon Sep 17 00:00:00 2001
From: Ricardo JL Rufino <ricardo.jl.rufino@gmail.com>
Date: Wed, 13 May 2020 21:49:35 -0300
Subject: [PATCH 4/5] (Codacy fix) Avoid unused imports

---
 app/src/processing/app/Theme.java | 2 --
 1 file changed, 2 deletions(-)

diff --git a/app/src/processing/app/Theme.java b/app/src/processing/app/Theme.java
index 9cbba7ef30a..34c9d2b9d34 100644
--- a/app/src/processing/app/Theme.java
+++ b/app/src/processing/app/Theme.java
@@ -69,8 +69,6 @@
 import org.apache.commons.compress.utils.IOUtils;
 import org.apache.commons.lang3.StringUtils;
 
-import processing.app.Theme.ZippedTheme;
-import processing.app.helpers.FileUtils;
 import processing.app.helpers.OSUtils;
 import processing.app.helpers.PreferencesHelper;
 import processing.app.helpers.PreferencesMap;

From 459d7a31a2bd0fdaebe724539e31d8f157eff206 Mon Sep 17 00:00:00 2001
From: Ricardo JL Rufino <ricardo.jl.rufino@gmail.com>
Date: Wed, 13 May 2020 21:49:35 -0300
Subject: [PATCH 5/5] (Codacy fix) Avoid unused imports

---
 app/src/cc/arduino/view/preferences/Preferences.java | 2 --
 app/src/processing/app/Theme.java                    | 2 --
 2 files changed, 4 deletions(-)

diff --git a/app/src/cc/arduino/view/preferences/Preferences.java b/app/src/cc/arduino/view/preferences/Preferences.java
index 8ae8a805986..89af1f7df76 100644
--- a/app/src/cc/arduino/view/preferences/Preferences.java
+++ b/app/src/cc/arduino/view/preferences/Preferences.java
@@ -48,14 +48,12 @@
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
 import java.awt.event.WindowEvent;
 import java.io.File;
 import java.io.IOException;
 import java.util.Collection;
 import java.util.LinkedList;
 
-import static processing.app.I18n.format;
 import static processing.app.I18n.tr;
 
 public class Preferences extends javax.swing.JDialog {
diff --git a/app/src/processing/app/Theme.java b/app/src/processing/app/Theme.java
index 9cbba7ef30a..34c9d2b9d34 100644
--- a/app/src/processing/app/Theme.java
+++ b/app/src/processing/app/Theme.java
@@ -69,8 +69,6 @@
 import org.apache.commons.compress.utils.IOUtils;
 import org.apache.commons.lang3.StringUtils;
 
-import processing.app.Theme.ZippedTheme;
-import processing.app.helpers.FileUtils;
 import processing.app.helpers.OSUtils;
 import processing.app.helpers.PreferencesHelper;
 import processing.app.helpers.PreferencesMap;