diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemeInfo.java b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemeInfo.java index e90bfaee..0f4049e1 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemeInfo.java +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemeInfo.java @@ -21,9 +21,17 @@ package com.formdev.flatlaf.demo.intellijthemes; */ class IJThemeInfo { - String name; - String resourceName; - String sourceCodeUrl; + final String name; + final String resourceName; + final String sourceCodeUrl; + final String lafClassName; + + IJThemeInfo( String name, String resourceName, String sourceCodeUrl, String lafClassName ) { + this.name = name; + this.resourceName = resourceName; + this.sourceCodeUrl = sourceCodeUrl; + this.lafClassName = lafClassName; + } @Override public String toString() { diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesManager.java b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesManager.java index dd246e5b..69b21666 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesManager.java +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesManager.java @@ -46,11 +46,7 @@ class IJThemesManager String resourceName = (String) e.getKey(); List strs = StringUtils.split( (String) e.getValue(), ',' ); - IJThemeInfo themeInfo = new IJThemeInfo(); - themeInfo.name = strs.get( 0 ); - themeInfo.resourceName = resourceName; - themeInfo.sourceCodeUrl = strs.get( 1 ); - bundledThemes.add( themeInfo ); + bundledThemes.add( new IJThemeInfo( strs.get( 0 ), resourceName, strs.get( 1 ), null ) ); } } } diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesPanel.java b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesPanel.java index f110a3cd..0f268cb7 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesPanel.java +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesPanel.java @@ -16,14 +16,20 @@ package com.formdev.flatlaf.demo.intellijthemes; +import java.awt.Component; import java.awt.EventQueue; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.List; import javax.swing.*; +import javax.swing.border.CompoundBorder; import javax.swing.event.*; +import com.formdev.flatlaf.FlatDarculaLaf; +import com.formdev.flatlaf.FlatDarkLaf; +import com.formdev.flatlaf.FlatIntelliJLaf; import com.formdev.flatlaf.FlatLaf; +import com.formdev.flatlaf.FlatLightLaf; import com.formdev.flatlaf.IntelliJTheme; import net.miginfocom.swing.*; @@ -34,6 +40,7 @@ public class IJThemesPanel extends JPanel { private final IJThemesManager themesManager = new IJThemesManager(); + private final List themes = new ArrayList<>(); private final PropertyChangeListener lafListener = this::lafChanged; public IJThemesPanel() { @@ -43,9 +50,16 @@ public class IJThemesPanel themesManager.loadBundledThemes(); // sort themes by name - List themes = new ArrayList<>(); themes.addAll( themesManager.bundledThemes ); themes.sort( (t1, t2) -> t1.name.compareToIgnoreCase( t2.name ) ); + int intellijThemesCount = themes.size(); + + // insert core themes at beginning + themes.add( 0, new IJThemeInfo( "Flat Light", null, null, FlatLightLaf.class.getName() ) ); + themes.add( 1, new IJThemeInfo( "Flat Dark", null, null, FlatDarkLaf.class.getName() ) ); + themes.add( 2, new IJThemeInfo( "Flat IntelliJ", null, null, FlatIntelliJLaf.class.getName() ) ); + themes.add( 3, new IJThemeInfo( "Flat Darcula", null, null, FlatDarculaLaf.class.getName() ) ); + int coreThemesCount = themes.size() - intellijThemesCount; // fill themes list themesList.setModel( new AbstractListModel() { @@ -58,6 +72,19 @@ public class IJThemesPanel return themes.get( index ); } } ); + + themesList.setCellRenderer( new DefaultListCellRenderer() { + @Override + public Component getListCellRendererComponent( JList list, Object value, + int index, boolean isSelected, boolean cellHasFocus ) + { + String title = (index == 0) ? "Core Themes" : (index == coreThemesCount ? "IntelliJ Themes" : null); + JComponent c = (JComponent) super.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus ); + if( title != null ) + c.setBorder( new CompoundBorder( new ListCellTitledBorder( themesList, title ), c.getBorder() ) ); + return c; + } + } ); } private void themesListValueChanged( ListSelectionEvent e ) { @@ -74,7 +101,14 @@ public class IJThemesPanel return; // change look and feel - IntelliJTheme.install( getClass().getResourceAsStream( themeInfo.resourceName ) ); + if( themeInfo.lafClassName != null ) { + try { + UIManager.setLookAndFeel( themeInfo.lafClassName ); + } catch( Exception ex ) { + ex.printStackTrace(); + } + } else + IntelliJTheme.install( getClass().getResourceAsStream( themeInfo.resourceName ) ); // update all components FlatLaf.updateUI(); @@ -103,8 +137,21 @@ public class IJThemesPanel private void selectedCurrentLookAndFeel() { LookAndFeel lookAndFeel = UIManager.getLookAndFeel(); - if( !(lookAndFeel instanceof IntelliJTheme.ThemeLaf) ) - themesList.clearSelection(); + int newSel = -1; + if( !(lookAndFeel instanceof IntelliJTheme.ThemeLaf) ) { + String lafClassName = lookAndFeel.getClass().getName(); + for( int i = 0; i < themes.size(); i++ ) { + if( lafClassName.equals( themes.get( i ).lafClassName ) ) { + newSel = i; + break; + } + } + + if( newSel >= 0 ) + themesList.setSelectedIndex( newSel ); + else + themesList.clearSelection(); + } } private void initComponents() { diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/ListCellTitledBorder.java b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/ListCellTitledBorder.java new file mode 100644 index 00000000..d3662d66 --- /dev/null +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/ListCellTitledBorder.java @@ -0,0 +1,89 @@ +/* + * Copyright 2019 FormDev Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.formdev.flatlaf.demo.intellijthemes; + +import java.awt.*; +import java.awt.geom.Rectangle2D; +import javax.swing.JList; +import javax.swing.UIManager; +import javax.swing.border.Border; +import com.formdev.flatlaf.ui.FlatUIUtils; +import com.formdev.flatlaf.util.UIScale; + +/** + * @author Karl Tauber + */ +class ListCellTitledBorder + implements Border +{ + private final JList list; + private final String title; + + ListCellTitledBorder( JList list, String title ) { + this.list = list; + this.title = title; + } + + @Override + public boolean isBorderOpaque() { + return true; + } + + @Override + public Insets getBorderInsets( Component c ) { + int height = c.getFontMetrics( list.getFont() ).getHeight(); + return new Insets( height, 0, 0, 0 ); + } + + @Override + public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) { + FontMetrics fm = c.getFontMetrics( list.getFont() ); + int titleWidth = fm.stringWidth( title ); + int titleHeight = fm.getHeight(); + + // fill background + g.setColor( list.getBackground() ); + g.fillRect( x, y, width, titleHeight ); + + int gap = UIScale.scale( 4 ); + + Graphics2D g2 = (Graphics2D) g.create(); + try { + FlatUIUtils.setRenderingHints( g2 ); + + g2.setColor( UIManager.getColor( "Label.disabledForeground" ) ); + + // paint separator lines + int sepWidth = (width - titleWidth) / 2 - gap - gap; + if( sepWidth > 0 ) { + int sy = y + Math.round( titleHeight / 2f ); + float sepHeight = UIScale.scale( (float) 1 ); + + g2.fill( new Rectangle2D.Float( x + gap, sy, sepWidth, sepHeight ) ); + g2.fill( new Rectangle2D.Float( x + width - gap - sepWidth, sy, sepWidth, sepHeight ) ); + } + + // draw title + int xt = x + ((width - titleWidth) / 2); + int yt = y + fm.getAscent(); + + FlatUIUtils.drawString( list, g2, title, xt, yt ); + } finally { + g2.dispose(); + } + } +}