IntelliJ Themes: added "Save" and "GitHub" buttons to themes list toolbar in demo (and testing apps) to allow users quickly save .theme.json files (including license) or visit theme source code repository

This commit is contained in:
Karl Tauber
2019-11-29 10:24:04 +01:00
parent d5c9bcddc8
commit f37c4cdc4d
9 changed files with 259 additions and 11 deletions

View File

@@ -25,16 +25,22 @@ class IJThemeInfo
{
final String name;
final String resourceName;
final String license;
final String licenseFile;
final String sourceCodeUrl;
final String sourceCodePath;
final File themeFile;
final String lafClassName;
IJThemeInfo( String name, String resourceName, String sourceCodeUrl, String sourceCodePath,
IJThemeInfo( String name, String resourceName,
String license, String licenseFile,
String sourceCodeUrl, String sourceCodePath,
File themeFile, String lafClassName )
{
this.name = name;
this.resourceName = resourceName;
this.license = license;
this.licenseFile = licenseFile;
this.sourceCodeUrl = sourceCodeUrl;
this.sourceCodePath = sourceCodePath;
this.themeFile = themeFile;

View File

@@ -55,10 +55,12 @@ class IJThemesManager
String resourceName = e.getKey();
Map<String, String> value = (Map<String, String>) e.getValue();
String name = value.get( "name" );
String license = value.get( "license" );
String licenseFile = value.get( "licenseFile" );
String sourceCodeUrl = value.get( "sourceCodeUrl" );
String sourceCodePath = value.get( "sourceCodePath" );
bundledThemes.add( new IJThemeInfo( name, resourceName, sourceCodeUrl, sourceCodePath, null, null ) );
bundledThemes.add( new IJThemeInfo( name, resourceName, license, licenseFile, sourceCodeUrl, sourceCodePath, null, null ) );
}
}
@@ -76,7 +78,7 @@ class IJThemesManager
moreThemes.clear();
for( File f : themeFiles ) {
String name = StringUtils.removeTrailing( f.getName(), ".theme.json" );
moreThemes.add( new IJThemeInfo( name, null, null, null, f, null ) );
moreThemes.add( new IJThemeInfo( name, null, null, null, null, null, f, null ) );
lastModifiedMap.put( f, f.lastModified() );
}
}

View File

@@ -17,6 +17,7 @@
package com.formdev.flatlaf.demo.intellijthemes;
import java.awt.Component;
import java.awt.Desktop;
import java.awt.EventQueue;
import java.awt.Window;
import java.awt.event.WindowAdapter;
@@ -24,7 +25,13 @@ import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
@@ -39,6 +46,8 @@ import com.formdev.flatlaf.FlatIntelliJLaf;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.FlatLightLaf;
import com.formdev.flatlaf.IntelliJTheme;
import com.formdev.flatlaf.extras.FlatSVGIcon;
import com.formdev.flatlaf.util.StringUtils;
import net.miginfocom.swing.*;
/**
@@ -59,9 +68,16 @@ public class IJThemesPanel
};
private Window window;
private File lastDirectory;
public IJThemesPanel() {
initComponents();
saveButton.setEnabled( false );
sourceCodeButton.setEnabled( false );
saveButton.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/download.svg" ) );
sourceCodeButton.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/github.svg" ) );
// create renderer
themesList.setCellRenderer( new DefaultListCellRenderer() {
@Override
@@ -75,10 +91,22 @@ public class IJThemesPanel
name = name.substring( sep + 1 ).trim();
JComponent c = (JComponent) super.getListCellRendererComponent( list, name, index, isSelected, cellHasFocus );
c.setToolTipText( buildToolTip( (IJThemeInfo) value ) );
if( title != null )
c.setBorder( new CompoundBorder( new ListCellTitledBorder( themesList, title ), c.getBorder() ) );
return c;
}
private String buildToolTip( IJThemeInfo ti ) {
if( ti.themeFile != null )
return ti.themeFile.getPath();
if( ti.resourceName == null )
return ti.name;
return "Name: " + ti.name
+ "\nLicense: " + ti.license
+ "\nSource Code: " + ti.sourceCodeUrl;
}
} );
updateThemesList();
@@ -99,10 +127,10 @@ public class IJThemesPanel
// add core themes at beginning
categories.put( themes.size(), "Core Themes" );
themes.add( new IJThemeInfo( "Flat Light", null, null, null, null, FlatLightLaf.class.getName() ) );
themes.add( new IJThemeInfo( "Flat Dark", null, null, null, null, FlatDarkLaf.class.getName() ) );
themes.add( new IJThemeInfo( "Flat IntelliJ", null, null, null, null, FlatIntelliJLaf.class.getName() ) );
themes.add( new IJThemeInfo( "Flat Darcula", null, null, null, null, FlatDarculaLaf.class.getName() ) );
themes.add( new IJThemeInfo( "Flat Light", null, null, null, null, null, null, FlatLightLaf.class.getName() ) );
themes.add( new IJThemeInfo( "Flat Dark", null, null, null, null, null, null, FlatDarkLaf.class.getName() ) );
themes.add( new IJThemeInfo( "Flat IntelliJ", null, null, null, null, null, null, FlatIntelliJLaf.class.getName() ) );
themes.add( new IJThemeInfo( "Flat Darcula", null, null, null, null, null, null, FlatDarculaLaf.class.getName() ) );
// add uncategorized bundled themes
categories.put( themes.size(), "IntelliJ Themes" );
@@ -166,8 +194,13 @@ public class IJThemesPanel
if( e.getValueIsAdjusting() )
return;
IJThemeInfo themeInfo = themesList.getSelectedValue();
boolean bundledTheme = (themeInfo != null && themeInfo.resourceName != null);
saveButton.setEnabled( bundledTheme );
sourceCodeButton.setEnabled( bundledTheme );
EventQueue.invokeLater( () -> {
setTheme( themesList.getSelectedValue() );
setTheme( themeInfo );
} );
}
@@ -200,8 +233,59 @@ public class IJThemesPanel
FlatLaf.updateUI();
}
private void saveTheme() {
IJThemeInfo themeInfo = themesList.getSelectedValue();
if( themeInfo == null || themeInfo.resourceName == null )
return;
JFileChooser fileChooser = new JFileChooser();
fileChooser.setSelectedFile( new File( lastDirectory, themeInfo.resourceName ) );
if( fileChooser.showSaveDialog( SwingUtilities.windowForComponent( this ) ) != JFileChooser.APPROVE_OPTION )
return;
File file = fileChooser.getSelectedFile();
lastDirectory = file.getParentFile();
// save theme
try {
Files.copy( getClass().getResourceAsStream( themeInfo.resourceName ),
file.toPath(), StandardCopyOption.REPLACE_EXISTING );
} catch( IOException ex ) {
showInformationDialog( "Failed to save theme to '" + file + "'.", ex );
return;
}
// save license
if( themeInfo.licenseFile != null ) {
try {
File licenseFile = new File( file.getParentFile(),
StringUtils.removeTrailing( file.getName(), ".theme.json" ) +
themeInfo.licenseFile.substring( themeInfo.licenseFile.indexOf( '.' ) ) );
Files.copy( getClass().getResourceAsStream( themeInfo.licenseFile ),
licenseFile.toPath(), StandardCopyOption.REPLACE_EXISTING );
} catch( IOException ex ) {
showInformationDialog( "Failed to save theme license to '" + file + "'.", ex );
return;
}
}
}
private void browseSourceCode() {
IJThemeInfo themeInfo = themesList.getSelectedValue();
if( themeInfo == null || themeInfo.resourceName == null )
return;
String themeUrl = (themeInfo.sourceCodeUrl + '/' + themeInfo.sourceCodePath).replace( " ", "%20" );
try {
Desktop.getDesktop().browse( new URI( themeUrl ) );
} catch( IOException | URISyntaxException ex ) {
showInformationDialog( "Failed to browse '" + themeUrl + "'.", ex );
}
}
private void showInformationDialog( String message, Exception ex ) {
JOptionPane.showMessageDialog( null, message + "\n\n" + ex.getMessage(),
JOptionPane.showMessageDialog( SwingUtilities.windowForComponent( this ),
message + "\n\n" + ex.getMessage(),
"FlatLaf", JOptionPane.INFORMATION_MESSAGE );
}
@@ -263,6 +347,9 @@ public class IJThemesPanel
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
JLabel themesLabel = new JLabel();
toolBar = new JToolBar();
saveButton = new JButton();
sourceCodeButton = new JButton();
themesScrollPane = new JScrollPane();
themesList = new JList<>();
@@ -272,13 +359,29 @@ public class IJThemesPanel
// columns
"[grow,fill]",
// rows
"[]" +
"[]3" +
"[grow,fill]"));
//---- themesLabel ----
themesLabel.setText("Themes:");
add(themesLabel, "cell 0 0");
//======== toolBar ========
{
toolBar.setFloatable(false);
//---- saveButton ----
saveButton.setToolTipText("Save .theme.json of selected IntelliJ theme to file.");
saveButton.addActionListener(e -> saveTheme());
toolBar.add(saveButton);
//---- sourceCodeButton ----
sourceCodeButton.setToolTipText("Opens the source code repository of selected IntelliJ theme in the browser.");
sourceCodeButton.addActionListener(e -> browseSourceCode());
toolBar.add(sourceCodeButton);
}
add(toolBar, "cell 0 0,alignx right,growx 0");
//======== themesScrollPane ========
{
@@ -292,6 +395,9 @@ public class IJThemesPanel
}
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
private JToolBar toolBar;
private JButton saveButton;
private JButton sourceCodeButton;
private JScrollPane themesScrollPane;
private JList<IJThemeInfo> themesList;
// JFormDesigner - End of variables declaration //GEN-END:variables

View File

@@ -6,7 +6,7 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets dialog,hidemode 3"
"$columnConstraints": "[grow,fill]"
"$rowConstraints": "[][grow,fill]"
"$rowConstraints": "[]3[grow,fill]"
} ) {
name: "this"
add( new FormComponent( "javax.swing.JLabel" ) {
@@ -18,6 +18,22 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0"
} )
add( new FormContainer( "javax.swing.JToolBar", new FormLayoutManager( class javax.swing.JToolBar ) ) {
name: "toolBar"
"floatable": false
add( new FormComponent( "javax.swing.JButton" ) {
name: "saveButton"
"toolTipText": "Save .theme.json of selected IntelliJ theme to file."
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "saveTheme", false ) )
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "sourceCodeButton"
"toolTipText": "Opens the source code repository of selected IntelliJ theme in the browser."
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "browseSourceCode", false ) )
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0,alignx right,growx 0"
} )
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
name: "themesScrollPane"
add( new FormComponent( "javax.swing.JList" ) {