From d784c0e74856c8368b45d21cae6e16e0fa878c2e Mon Sep 17 00:00:00 2001 From: weisj Date: Sun, 20 Oct 2019 20:26:13 +0200 Subject: [PATCH] Fixed undesired behaviour when the TabbedPane becomes empty through a DnD action. Fixed selection foreground when not focused for Tree/Table/List. --- .gitignore | 1 + build.gradle | 35 ++++++++++++----- darklaf.iml | 2 +- gradle.properties | 6 ++- settings.gradle | 4 -- .../components/ClosableTabComponent.java | 6 ++- .../components/ClosableTabbedPane.java | 12 +++++- .../components/tabframe/JTabFrame.java | 11 ++++++ .../components/tabframe/TabFrameContent.java | 8 ++++ .../tabframe/TabFrameContentPane.java | 29 ++++++++------ .../com/weis/darklaf/icons/IconLoader.java | 7 ++-- .../com/weis/darklaf/theme/DarculaTheme.java | 4 +- .../java/com/weis/darklaf/theme/Theme.java | 10 ++--- .../ui/cell/DarkCellRendererToggleButton.java | 13 ++++++- .../darklaf/ui/list/DarkListCellRenderer.java | 7 +++- .../darklaf/ui/tabbedpane/DarkHandler.java | 8 ++-- .../ui/tabbedpane/DarkScrollableTabPanel.java | 32 ++++++++------- .../DarkTabbedPaneScrollLayout.java | 39 +++++++++++-------- .../ui/tabbedpane/DarkTabbedPaneUI.java | 32 +++++++++++++++ .../darklaf/ui/tabbedpane/NewTabButton.java | 1 + .../tabbedpane/TabbedPaneTransferHandler.java | 2 + .../darklaf/ui/tabbedpane/TabbedPaneUtil.java | 14 +++++-- .../darklaf/ui/tabframe/DarkPanelPopupUI.java | 2 + .../darklaf/ui/tabframe/DarkTabFrameUI.java | 16 +------- .../DarkTableCellEditorToggleButton.java | 7 +++- .../ui/table/DarkTableCellRenderer.java | 6 ++- .../darklaf/ui/tree/DarkTreeCellEditor.java | 9 +++++ .../darklaf/ui/tree/DarkTreeCellRenderer.java | 8 +++- .../darklaf/properties/ui/list.properties | 3 +- .../darklaf/properties/ui/table.properties | 1 + .../darklaf/properties/ui/tree.properties | 2 + .../intellij/intellij_defaults.properties | 2 +- src/test/java/TabFrameDemo.java | 27 +++++++++++++ src/test/java/TabbedPaneDemo.java | 6 ++- 34 files changed, 270 insertions(+), 102 deletions(-) diff --git a/.gitignore b/.gitignore index 034020f3..41bd4947 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,7 @@ target/ # gradle /build /.gradle +gradle.properties # Python venv/ diff --git a/build.gradle b/build.gradle index ecdeffd7..1d449bfe 100644 --- a/build.gradle +++ b/build.gradle @@ -27,7 +27,32 @@ dependencies { group = 'com.weis' -version = '1.0-SNAPSHOT' +version = '1.3' + +task sourceJar(type: Jar, dependsOn: classes) { + classifier 'sources' + from sourceSets.main.allSource +} + + +publishing { + publications { + maven(MavenPublication) { + from components.java + artifact tasks.sourceJar + } + } + repositories { + maven { + name 'deploy' + url deployRepoUrl + credentials { + username = deployRepoUsername + password = deployRepoPassword + } + } + } +} println "Building on OS: " + System.properties['os.name'] println "Using JDK: " + System.properties['java.home'] @@ -64,14 +89,6 @@ model { } } -publishing { - publications { - maven(MavenPublication) { - from(components.java) - } - } -} - tasks.withType(JavaCompile) { dependsOn 'copyLibraries' configure(options) { diff --git a/darklaf.iml b/darklaf.iml index b3c2bd97..036d1459 100644 --- a/darklaf.iml +++ b/darklaf.iml @@ -1,5 +1,5 @@ - + diff --git a/gradle.properties b/gradle.properties index ca437fe5..f435f9f0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1,5 @@ -org.gradle.warning.mode = all \ No newline at end of file +org.gradle.warning.mode = all +externalVersion = 1.0-SNAPSHOT +deployRepoUrl = https://my-repo.com/maven-snapshots +deployRepoUsername = your-username +deployRepoPassword = your-password \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 65956fd8..afa1bb6b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1 @@ -/* - * This file was generated by the Gradle 'init' task. - */ - rootProject.name = 'darklaf' diff --git a/src/main/java/com/weis/darklaf/components/ClosableTabComponent.java b/src/main/java/com/weis/darklaf/components/ClosableTabComponent.java index e75f0eec..daee8f2d 100644 --- a/src/main/java/com/weis/darklaf/components/ClosableTabComponent.java +++ b/src/main/java/com/weis/darklaf/components/ClosableTabComponent.java @@ -15,7 +15,7 @@ import java.awt.event.MouseListener; */ public class ClosableTabComponent extends JPanel { - private final JTabbedPane pane; + private JTabbedPane pane; public ClosableTabComponent(final JTabbedPane pane) { super(new FlowLayout(FlowLayout.LEFT, 0, 0)); @@ -28,6 +28,10 @@ public class ClosableTabComponent extends JPanel { add(new TabButton(this)); } + public void setTabbedPane(final JTabbedPane pane) { + this.pane = pane; + } + protected static class TabLabel extends JLabel { private ClosableTabComponent tabComponent; diff --git a/src/main/java/com/weis/darklaf/components/ClosableTabbedPane.java b/src/main/java/com/weis/darklaf/components/ClosableTabbedPane.java index bc15b972..73aa5b11 100644 --- a/src/main/java/com/weis/darklaf/components/ClosableTabbedPane.java +++ b/src/main/java/com/weis/darklaf/components/ClosableTabbedPane.java @@ -23,15 +23,23 @@ public class ClosableTabbedPane extends JTabbedPane { notifyTabListeners(new TabEvent(this, TabEvent.TAB_OPENED, "tabOpened", index)); } + @Override + public void setTabComponentAt(final int index, final Component component) { + if (component instanceof ClosableTabComponent) { + ((ClosableTabComponent) component).setTabbedPane(this); + } + super.setTabComponentAt(index, component); + } + @Override public void removeTabAt(final int index) { checkIndex(index); - if (notifyVetoableChangeListeners(new TabPropertyChangeEvent(this, "tabOpened", + if (notifyVetoableChangeListeners(new TabPropertyChangeEvent(this, "tabClosed", getComponentAt(index), null, index))) { return; } + notifyTabListeners(new TabEvent(this, TabEvent.TAB_CLOSED, "tabClosed", index)); super.removeTabAt(index); - notifyTabListeners(new TabEvent(this, TabEvent.TAB_CLOSED, "tabOpened", index)); } private void checkIndex(final int index) { diff --git a/src/main/java/com/weis/darklaf/components/tabframe/JTabFrame.java b/src/main/java/com/weis/darklaf/components/tabframe/JTabFrame.java index d50483b4..ca54de08 100644 --- a/src/main/java/com/weis/darklaf/components/tabframe/JTabFrame.java +++ b/src/main/java/com/weis/darklaf/components/tabframe/JTabFrame.java @@ -924,6 +924,17 @@ public class JTabFrame extends JComponent { firePropertyChange("dndEnabled", old, dndEnabled); } + /** + * Set the component at the given position. + * + * @param c the component. + * @param a the alignment position.{@link TabFramePosition#getAlignment()} + * @param index the index.{@link TabFramePosition#getIndex()} + */ + public void setComponentAt(final Component c, final Alignment a, final int index) { + compsForAlignment(a).get(index).setContentPane(c); + } + /** * This class represents a position inside the tabFrame. */ diff --git a/src/main/java/com/weis/darklaf/components/tabframe/TabFrameContent.java b/src/main/java/com/weis/darklaf/components/tabframe/TabFrameContent.java index 878f7411..070b81ac 100644 --- a/src/main/java/com/weis/darklaf/components/tabframe/TabFrameContent.java +++ b/src/main/java/com/weis/darklaf/components/tabframe/TabFrameContent.java @@ -80,4 +80,12 @@ public interface TabFrameContent { * @return the enabled status. */ boolean[] getStatus(); + + /** + * Get the popup container at the given location. + * + * @param alignment the alignment position. + * @return the popup container. + */ + PopupContainer getContainer(Alignment alignment); } diff --git a/src/main/java/com/weis/darklaf/components/tabframe/TabFrameContentPane.java b/src/main/java/com/weis/darklaf/components/tabframe/TabFrameContentPane.java index 09036c25..77c73945 100644 --- a/src/main/java/com/weis/darklaf/components/tabframe/TabFrameContentPane.java +++ b/src/main/java/com/weis/darklaf/components/tabframe/TabFrameContentPane.java @@ -382,37 +382,42 @@ public class TabFrameContentPane extends JPanel implements TabFrameContent { * @return the popup component at position. */ @NotNull - public PanelPopup getPopupComponent(@NotNull final Alignment a) { - Component popupComponent; - switch (a) { + public Component getPopupComponent(@NotNull final Alignment a) { + return getContainer(a).getPopup(); + } + + @Override + public PopupContainer getContainer(@NotNull final Alignment alignment) { + PopupContainer popupComponent; + switch (alignment) { case NORTH: - popupComponent = ((PopupContainer) topSplitter.getLeftComponent()).getPopup(); + popupComponent = ((PopupContainer) topSplitter.getLeftComponent()); break; case NORTH_EAST: - popupComponent = ((PopupContainer) topSplitter.getRightComponent()).getPopup(); + popupComponent = ((PopupContainer) topSplitter.getRightComponent()); break; case EAST: - popupComponent = ((PopupContainer) rightSplitter.getTopComponent()).getPopup(); + popupComponent = ((PopupContainer) rightSplitter.getTopComponent()); break; case SOUTH_EAST: - popupComponent = ((PopupContainer) rightSplitter.getBottomComponent()).getPopup(); + popupComponent = ((PopupContainer) rightSplitter.getBottomComponent()); break; case SOUTH: - popupComponent = ((PopupContainer) bottomSplitter.getRightComponent()).getPopup(); + popupComponent = ((PopupContainer) bottomSplitter.getRightComponent()); break; case SOUTH_WEST: - popupComponent = ((PopupContainer) bottomSplitter.getLeftComponent()).getPopup(); + popupComponent = ((PopupContainer) bottomSplitter.getLeftComponent()); break; case WEST: - popupComponent = ((PopupContainer) leftSplitter.getBottomComponent()).getPopup(); + popupComponent = ((PopupContainer) leftSplitter.getBottomComponent()); break; case NORTH_WEST: - popupComponent = ((PopupContainer) leftSplitter.getTopComponent()).getPopup(); + popupComponent = ((PopupContainer) leftSplitter.getTopComponent()); break; default: throw new IllegalArgumentException("CENTER is not supported"); } - return (PanelPopup) popupComponent; + return popupComponent; } protected static class LayoutProportions { diff --git a/src/main/java/com/weis/darklaf/icons/IconLoader.java b/src/main/java/com/weis/darklaf/icons/IconLoader.java index 3c90de8e..3a7c97f0 100644 --- a/src/main/java/com/weis/darklaf/icons/IconLoader.java +++ b/src/main/java/com/weis/darklaf/icons/IconLoader.java @@ -61,7 +61,9 @@ public final class IconLoader { if (iconLoaderMap.containsKey(parentClass)) { return iconLoaderMap.get(parentClass); } else { - return new IconLoader(parentClass); + var loader = new IconLoader(parentClass); + iconLoaderMap.put(parentClass, loader); + return loader; } } @@ -86,7 +88,7 @@ public final class IconLoader { @Contract(value = "_, _, _ -> new", pure = true) @NotNull public DarkUIAwareIcon create(@NotNull final String name, final int w, final int h) { - return new DarkUIAwareIcon("dark/" + name, "light/" + name, w, h, IconLoader.class); + return new DarkUIAwareIcon("dark/" + name, "light/" + name, w, h, parentClass); } public Icon getIcon(final String path) { @@ -130,7 +132,6 @@ public final class IconLoader { } @NotNull - @Contract("_, _, _ -> new") public Icon loadSVGIcon(@NotNull final String name, final int w, final int h, final boolean themed) { try { LOGGER.info("Loading icon '" + name + "'. Resolving from " + parentClass); diff --git a/src/main/java/com/weis/darklaf/theme/DarculaTheme.java b/src/main/java/com/weis/darklaf/theme/DarculaTheme.java index 34cb65a9..9e8b3494 100644 --- a/src/main/java/com/weis/darklaf/theme/DarculaTheme.java +++ b/src/main/java/com/weis/darklaf/theme/DarculaTheme.java @@ -12,11 +12,13 @@ public class DarculaTheme extends Theme { @Override public String getName() { - return "Darcula"; + return "darcula"; } @Override public boolean isDark() { return true; } + + } diff --git a/src/main/java/com/weis/darklaf/theme/Theme.java b/src/main/java/com/weis/darklaf/theme/Theme.java index c16ddaa4..ccaffb56 100644 --- a/src/main/java/com/weis/darklaf/theme/Theme.java +++ b/src/main/java/com/weis/darklaf/theme/Theme.java @@ -61,18 +61,18 @@ public abstract class Theme { final Properties properties = new Properties(); try (InputStream stream = getResourceAsStream(name)) { properties.load(stream); - } catch (IOException e) { - LOGGER.log(Level.SEVERE, "Could not load" + name + ".properties", e.getMessage()); + } catch (Exception e) { + LOGGER.log(Level.SEVERE, "Could not load " + name + ".properties. " + e.getMessage(), e.getStackTrace()); } return properties; } protected InputStream getResourceAsStream(final String name) { - return getResourceAsStream(this.getClass(), name); + return getLoaderClass().getResourceAsStream(name); } - protected InputStream getResourceAsStream(@NotNull final Class clazz, final String name) { - return clazz.getResourceAsStream(name); + protected Class getLoaderClass() { + return this.getClass(); } /** diff --git a/src/main/java/com/weis/darklaf/ui/cell/DarkCellRendererToggleButton.java b/src/main/java/com/weis/darklaf/ui/cell/DarkCellRendererToggleButton.java index 7f136e44..42120836 100644 --- a/src/main/java/com/weis/darklaf/ui/cell/DarkCellRendererToggleButton.java +++ b/src/main/java/com/weis/darklaf/ui/cell/DarkCellRendererToggleButton.java @@ -26,6 +26,7 @@ package com.weis.darklaf.ui.cell; import com.weis.darklaf.components.SelectableTreeNode; import com.weis.darklaf.decorators.CellRenderer; import com.weis.darklaf.ui.tree.DarkTreeCellRenderer; +import com.weis.darklaf.util.DarkUIUtil; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -66,7 +67,11 @@ public class DarkCellRendererToggleButton Math.max(50, ui.maxTabHeight)) { - stopDrag(e); + stopDrag(e, false); TransferHandler handler = ui.tabPane.getTransferHandler(); handler.exportAsDrag(ui.tabPane, e, TransferHandler.MOVE); } @@ -228,10 +228,10 @@ public class DarkHandler extends TabbedPaneHandler { return p; } - protected void stopDrag(final MouseEvent e) { + protected void stopDrag(final MouseEvent e, final boolean changeTabs) { int tab = TabbedPaneUtil.getDroppedTabIndex(ui.dropRect, ui.tabPane, ui, getDragMousePos()); - if (tab >= 0 && tab <= ui.tabPane.getTabCount()) { + if (changeTabs && tab >= 0 && tab <= ui.tabPane.getTabCount()) { TabbedPaneUtil.moveTabs(ui.tabPane, ui.tabPane, ui.dropSourceIndex, tab); } SwingUtilities.invokeLater(() -> ui.setRolloverTab(e.getX(), e.getY())); diff --git a/src/main/java/com/weis/darklaf/ui/tabbedpane/DarkScrollableTabPanel.java b/src/main/java/com/weis/darklaf/ui/tabbedpane/DarkScrollableTabPanel.java index 737307f5..aca6cbe1 100644 --- a/src/main/java/com/weis/darklaf/ui/tabbedpane/DarkScrollableTabPanel.java +++ b/src/main/java/com/weis/darklaf/ui/tabbedpane/DarkScrollableTabPanel.java @@ -52,19 +52,21 @@ class DarkScrollableTabPanel extends ScrollableTabPanel { boolean leftToRight = ui.tabPane.getComponentOrientation().isLeftToRight(); int tabCount = ui.tabPane.getTabCount(); var b = child.getPreferredSize(); - if (ui.isHorizontalTabPlacement()) { - int off = ui.dropTargetIndex == tabCount ? ui.dropRect.width : 0; - if (leftToRight) { - int x = ui.rects[tabCount - 1].x + ui.rects[tabCount - 1].width + off; - child.setBounds(x, 0, b.width, ui.maxTabHeight); + if (tabCount > 0) { + if (ui.isHorizontalTabPlacement()) { + int off = ui.dropTargetIndex == tabCount ? ui.dropRect.width : 0; + if (leftToRight) { + int x = ui.rects[tabCount - 1].x + ui.rects[tabCount - 1].width + off; + child.setBounds(x, 0, b.width, ui.maxTabHeight); + } else { + int x = ui.rects[tabCount - 1].x - off; + child.setBounds(x - b.width, 0, b.width, ui.maxTabHeight); + } } else { - int x = ui.rects[tabCount - 1].x - off; - child.setBounds(x - b.width, 0, b.width, ui.maxTabHeight); + int off = ui.dropTargetIndex == tabCount ? ui.dropRect.height : 0; + int y = ui.rects[tabCount - 1].y + ui.rects[tabCount - 1].height + off; + child.setBounds(0, y, ui.maxTabWidth, b.height); } - } else { - int off = ui.dropTargetIndex == tabCount ? ui.dropRect.height : 0; - int y = ui.rects[tabCount - 1].y + ui.rects[tabCount - 1].height + off; - child.setBounds(0, y, ui.maxTabWidth, b.height); } } else { child.setBounds(0, 0, getWidth(), getHeight()); @@ -76,11 +78,13 @@ class DarkScrollableTabPanel extends ScrollableTabPanel { @Override public void paint(final Graphics g) { super.paint(g); - if (ui.dragging) { + if (ui.dragging && ui.tabPane.getTabCount() > 0) { ui.paintTab(g, ui.tabPane.getTabPlacement(), ui.dragRect, ui.tabPane.getSelectedIndex(), iconRect, textRect); var comp = ui.tabPane.getTabComponentAt(ui.dropSourceIndex); - g.translate(comp.getX(), comp.getY()); - comp.print(g); + if (comp != null) { + g.translate(comp.getX(), comp.getY()); + comp.print(g); + } } } } diff --git a/src/main/java/com/weis/darklaf/ui/tabbedpane/DarkTabbedPaneScrollLayout.java b/src/main/java/com/weis/darklaf/ui/tabbedpane/DarkTabbedPaneScrollLayout.java index 34dc55d7..5149ece6 100644 --- a/src/main/java/com/weis/darklaf/ui/tabbedpane/DarkTabbedPaneScrollLayout.java +++ b/src/main/java/com/weis/darklaf/ui/tabbedpane/DarkTabbedPaneScrollLayout.java @@ -256,23 +256,25 @@ public class DarkTabbedPaneScrollLayout extends TabbedPaneScrollLayout { // Calculate how much space the tabs will need, based on the // minimum size required to display largest child + content border // - if (!ui.isHorizontalTabPlacement()) { - int tabHeight = ui.calculateTabHeight(tabPlacement, ui.tabPane.getSelectedIndex(), - ui.getFontMetrics().getHeight()); - if (ui.scrollableTabSupport.moreTabsButton.isVisible()) { - tabHeight += ui.scrollableTabSupport.moreTabsButton.getPreferredSize().height; - } - height = Math.max(height, tabHeight); - tabExtent = preferredTabAreaWidth(tabPlacement, height - tabAreaInsets.top - tabAreaInsets.bottom); - width += tabExtent; - } else { - int tabWidth = ui.calculateTabWidth(tabPlacement, ui.tabPane.getSelectedIndex(), ui.getFontMetrics()); - if (ui.scrollableTabSupport.moreTabsButton.isVisible()) { - tabWidth += ui.scrollableTabSupport.moreTabsButton.getPreferredSize().width; + if (ui.tabPane.getTabCount() > 0) { + if (!ui.isHorizontalTabPlacement()) { + int tabHeight = ui.calculateTabHeight(tabPlacement, ui.tabPane.getSelectedIndex(), + ui.getFontMetrics().getHeight()); + if (ui.scrollableTabSupport.moreTabsButton.isVisible()) { + tabHeight += ui.scrollableTabSupport.moreTabsButton.getPreferredSize().height; + } + height = Math.max(height, tabHeight); + tabExtent = preferredTabAreaWidth(tabPlacement, height - tabAreaInsets.top - tabAreaInsets.bottom); + width += tabExtent; + } else { + int tabWidth = ui.calculateTabWidth(tabPlacement, ui.tabPane.getSelectedIndex(), ui.getFontMetrics()); + if (ui.scrollableTabSupport.moreTabsButton.isVisible()) { + tabWidth += ui.scrollableTabSupport.moreTabsButton.getPreferredSize().width; + } + width = Math.max(width, tabWidth); + tabExtent = preferredTabAreaHeight(tabPlacement, width - tabAreaInsets.left - tabAreaInsets.right); + height += tabExtent; } - width = Math.max(width, tabWidth); - tabExtent = preferredTabAreaHeight(tabPlacement, width - tabAreaInsets.left - tabAreaInsets.right); - height += tabExtent; } return new Dimension(width + insets.left + insets.right + contentInsets.left + contentInsets.right, height + insets.bottom + insets.top + contentInsets.top + contentInsets.bottom); @@ -309,7 +311,9 @@ public class DarkTabbedPaneScrollLayout extends TabbedPaneScrollLayout { } JButton tabsButton = ui.scrollableTabSupport.moreTabsButton; - Rectangle selectedBounds = new Rectangle(ui.rects[ui.tabPane.getSelectedIndex()]); + Rectangle selectedBounds = ui.tabPane.getSelectedIndex() > 0 + ? new Rectangle(ui.rects[ui.tabPane.getSelectedIndex()]) + : new Rectangle(0, 0, 0, 0); if (!verticalTabRuns) { int rightMargin = size.width - (insets.right + tabAreaInsets.right + insets.left + tabAreaInsets.left); @@ -390,6 +394,7 @@ public class DarkTabbedPaneScrollLayout extends TabbedPaneScrollLayout { ui.tabScroller.tabPanel.invalidate(); } + @Override protected int preferredTabAreaWidth(final int tabPlacement, final int height) { return ui.calculateMaxTabWidth(tabPlacement); diff --git a/src/main/java/com/weis/darklaf/ui/tabbedpane/DarkTabbedPaneUI.java b/src/main/java/com/weis/darklaf/ui/tabbedpane/DarkTabbedPaneUI.java index 00ca7dbb..8a032ede 100644 --- a/src/main/java/com/weis/darklaf/ui/tabbedpane/DarkTabbedPaneUI.java +++ b/src/main/java/com/weis/darklaf/ui/tabbedpane/DarkTabbedPaneUI.java @@ -148,6 +148,10 @@ public class DarkTabbedPaneUI extends DarkTabbedPaneUIBridge { if (!scrollableTabLayoutEnabled() && drawDropRect) { paintDrop(g); } + + if (tabPane.getTabCount() == 0) { + paintTabAreaBorder(g, tabPlacement); + } } @Override @@ -659,6 +663,34 @@ public class DarkTabbedPaneUI extends DarkTabbedPaneUIBridge { p.x, p.y, e.getClickCount(), e.isPopupTrigger(), e.getButton()); } + @Override + protected int calculateMaxTabHeight(final int tabPlacement) { + return Math.max(super.calculateMaxTabHeight(tabPlacement), getFallBackSize()); + } + + @Override + protected int calculateMaxTabWidth(final int tabPlacement) { + return Math.max(super.calculateMaxTabWidth(tabPlacement), getFallBackSize()); + } + + @Override + protected int calculateTabAreaHeight(final int tabPlacement, final int horizRunCount, final int maxTabHeight) { + return Math.max(super.calculateTabAreaHeight(tabPlacement, horizRunCount, maxTabHeight), getFallBackSize()); + } + + @Override + protected int calculateTabAreaWidth(final int tabPlacement, final int vertRunCount, final int maxTabWidth) { + return Math.max(super.calculateTabAreaWidth(tabPlacement, vertRunCount, maxTabWidth), getFallBackSize()); + } + + protected int getFallBackSize() { + int max = 0; + if (scrollableTabLayoutEnabled() && scrollableTabSupport.newTabButton.isVisible()) { + max = Math.max(scrollableTabSupport.newTabButton.getPreferredSize().height, 27); + } + return max; + } + protected void layoutTabComponents() { if (tabContainer == null) { return; diff --git a/src/main/java/com/weis/darklaf/ui/tabbedpane/NewTabButton.java b/src/main/java/com/weis/darklaf/ui/tabbedpane/NewTabButton.java index e3a6bc81..c66485fe 100644 --- a/src/main/java/com/weis/darklaf/ui/tabbedpane/NewTabButton.java +++ b/src/main/java/com/weis/darklaf/ui/tabbedpane/NewTabButton.java @@ -57,6 +57,7 @@ public class NewTabButton extends JPanel implements UIResource { button.putClientProperty("JButton.thin", Boolean.TRUE); button.setRolloverEnabled(true); button.setOpaque(false); + button.setMargin(new Insets(2, 2, 2, 2)); return button; } diff --git a/src/main/java/com/weis/darklaf/ui/tabbedpane/TabbedPaneTransferHandler.java b/src/main/java/com/weis/darklaf/ui/tabbedpane/TabbedPaneTransferHandler.java index 8ad9c99f..f9156fc0 100644 --- a/src/main/java/com/weis/darklaf/ui/tabbedpane/TabbedPaneTransferHandler.java +++ b/src/main/java/com/weis/darklaf/ui/tabbedpane/TabbedPaneTransferHandler.java @@ -168,6 +168,8 @@ public class TabbedPaneTransferHandler extends TransferHandler implements DropTa } else { index = -1; } + var tabComp = tabPane.getTabComponentAt(index); + if (tabComp != null) tabComp.setVisible(false); tabPane.setSelectedIndex(index); if (ui != null) { ui.setRolloverTab(-1); diff --git a/src/main/java/com/weis/darklaf/ui/tabbedpane/TabbedPaneUtil.java b/src/main/java/com/weis/darklaf/ui/tabbedpane/TabbedPaneUtil.java index e15d2848..03ebfa07 100644 --- a/src/main/java/com/weis/darklaf/ui/tabbedpane/TabbedPaneUtil.java +++ b/src/main/java/com/weis/darklaf/ui/tabbedpane/TabbedPaneUtil.java @@ -94,6 +94,7 @@ public class TabbedPaneUtil implements SwingConstants { @NotNull final JTabbedPane destTabbedPane, final JTabbedPane source, final Point mouseLocation, final Rectangle tabBounds, final int tab, final int sourceIndex, final int lastTab) { + if (destTabbedPane.getTabCount() == 0) return new Rectangle(0, 0, 0, 0); int tabPlacement = destTabbedPane.getTabPlacement(); Rectangle destRect = destTabbedPane.getBoundsAt(Math.min(tab, destTabbedPane.getTabCount() - 1)); @@ -192,10 +193,14 @@ public class TabbedPaneUtil implements SwingConstants { if (tabbedPane == sourcePane && sourceIndex == tab) { //Nothing to do. Just select the tab to be sure. + var comp = sourcePane.getTabComponentAt(tab); + if (comp != null) comp.setVisible(true); selectTab(sourcePane, sourceIndex); return false; } - if (tab < 0 || tab > tabbedPane.getTabCount()) { + int destIndex = tab; + if (tabbedPane.getTabCount() == 0) destIndex = 0; + if (destIndex < 0 || destIndex > tabbedPane.getTabCount()) { return false; } @@ -206,18 +211,21 @@ public class TabbedPaneUtil implements SwingConstants { Color foreground = sourcePane.getForegroundAt(sourceIndex); Component tabComp = sourcePane.getTabComponentAt(sourceIndex); - tabbedPane.insertTab(tabName, icon, comp, toolTip, tab); + tabbedPane.insertTab(tabName, icon, comp, toolTip, destIndex); - int index = tab; + int index = destIndex; if (tabbedPane == sourcePane) { if (sourceIndex < index) index--; } if (tabComp != null) { + tabComp.setVisible(true); tabbedPane.setTabComponentAt(index, tabComp); } tabbedPane.setForegroundAt(index, foreground); selectTab(tabbedPane, index); + + sourcePane.revalidate(); return true; } diff --git a/src/main/java/com/weis/darklaf/ui/tabframe/DarkPanelPopupUI.java b/src/main/java/com/weis/darklaf/ui/tabframe/DarkPanelPopupUI.java index 6c17eae7..949f1127 100644 --- a/src/main/java/com/weis/darklaf/ui/tabframe/DarkPanelPopupUI.java +++ b/src/main/java/com/weis/darklaf/ui/tabframe/DarkPanelPopupUI.java @@ -358,6 +358,8 @@ public class DarkPanelPopupUI extends DarkPanelUI implements PropertyChangeListe if (focusOwner instanceof JTabFrame) return; if (focusOwner instanceof JRootPane) return; boolean focus = DarkUIUtil.hasFocus(popupComponent); + var container = popupComponent.getTabFrame().getContentPane().getContainer(popupComponent.getAlignment()); + focus = focus || DarkUIUtil.hasFocus(container); setHeaderBackground(focus); } } diff --git a/src/main/java/com/weis/darklaf/ui/tabframe/DarkTabFrameUI.java b/src/main/java/com/weis/darklaf/ui/tabframe/DarkTabFrameUI.java index 4fc28e08..ada43612 100644 --- a/src/main/java/com/weis/darklaf/ui/tabframe/DarkTabFrameUI.java +++ b/src/main/java/com/weis/darklaf/ui/tabframe/DarkTabFrameUI.java @@ -31,7 +31,6 @@ import com.weis.darklaf.components.tabframe.TabFramePopup; import com.weis.darklaf.components.tabframe.TabFrameTab; import com.weis.darklaf.components.tabframe.TabFrameUI; import com.weis.darklaf.components.uiresource.JPanelUIResource; -import com.weis.darklaf.util.DarkUIUtil; import com.weis.darklaf.util.Pair; import org.jdesktop.jxlayer.JXLayer; import org.jetbrains.annotations.Contract; @@ -551,19 +550,8 @@ public class DarkTabFrameUI extends TabFrameUI implements AWTEventListener { if (event.getID() == MouseEvent.MOUSE_PRESSED) { var e = (MouseEvent) event; var comp = e.getComponent().getComponentAt(e.getPoint()); - var parent = DarkUIUtil.getParentOfType(TabFramePopup.class, comp); - if (parent != null) { - parent.getComponent().requestFocus(); - return; - } - var parent2 = DarkUIUtil.getParentOfType(PopupContainer.class, comp); - if (parent2 != null) { - parent2.getPopup().requestFocus(); - return; - } - var parent3 = DarkUIUtil.getParentOfType(JTabFrame.class, comp); - if (parent3 != null && comp != null && !comp.hasFocus()) { - parent3.requestFocus(); + if (comp instanceof TabFramePopup || comp instanceof PopupContainer || comp instanceof JTabFrame) { + comp.requestFocus(); } } } diff --git a/src/main/java/com/weis/darklaf/ui/table/DarkTableCellEditorToggleButton.java b/src/main/java/com/weis/darklaf/ui/table/DarkTableCellEditorToggleButton.java index 193e801d..59773a1a 100644 --- a/src/main/java/com/weis/darklaf/ui/table/DarkTableCellEditorToggleButton.java +++ b/src/main/java/com/weis/darklaf/ui/table/DarkTableCellEditorToggleButton.java @@ -1,6 +1,7 @@ package com.weis.darklaf.ui.table; import com.weis.darklaf.decorators.CellRenderer; +import com.weis.darklaf.util.DarkUIUtil; import javax.swing.*; import javax.swing.table.TableCellEditor; @@ -39,7 +40,11 @@ public class DarkTableCellEditorToggleButton extends AbstractCellEditor implemen toggleButton.setBackground(background); toggleButton.setForeground(table.getForeground()); } else { - toggleButton.setForeground(table.getSelectionForeground()); + if (DarkUIUtil.hasFocus(table)) { + toggleButton.setForeground(table.getSelectionForeground()); + } else { + toggleButton.setForeground(UIManager.getColor("Table.selectionForegroundInactive")); + } toggleButton.setBackground(table.getSelectionBackground()); } return toggleButton; diff --git a/src/main/java/com/weis/darklaf/ui/table/DarkTableCellRenderer.java b/src/main/java/com/weis/darklaf/ui/table/DarkTableCellRenderer.java index f0119b9b..08e49304 100644 --- a/src/main/java/com/weis/darklaf/ui/table/DarkTableCellRenderer.java +++ b/src/main/java/com/weis/darklaf/ui/table/DarkTableCellRenderer.java @@ -66,7 +66,11 @@ public class DarkTableCellRenderer extends DefaultTableCellRenderer { component.setBackground(background); component.setForeground(table.getForeground()); } else { - component.setForeground(table.getSelectionForeground()); + if (DarkUIUtil.hasFocus(table)) { + component.setForeground(table.getSelectionForeground()); + } else { + component.setForeground(UIManager.getColor("Table.selectionForegroundInactive")); + } component.setBackground(table.getSelectionBackground()); } return component; diff --git a/src/main/java/com/weis/darklaf/ui/tree/DarkTreeCellEditor.java b/src/main/java/com/weis/darklaf/ui/tree/DarkTreeCellEditor.java index d6479c3e..fceccd41 100644 --- a/src/main/java/com/weis/darklaf/ui/tree/DarkTreeCellEditor.java +++ b/src/main/java/com/weis/darklaf/ui/tree/DarkTreeCellEditor.java @@ -24,6 +24,7 @@ package com.weis.darklaf.ui.tree; import com.weis.darklaf.components.SelectableTreeNode; +import com.weis.darklaf.util.DarkUIUtil; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -162,6 +163,14 @@ public class DarkTreeCellEditor extends DefaultCellEditor implements TreeCellEdi } editorComponent.setOpaque(false); editorComponent.setComponentOrientation(tree.getComponentOrientation()); + + if (isSelected && editorComponent instanceof JToggleButton) { + if (DarkUIUtil.hasFocus(tree)) { + editorComponent.setForeground(UIManager.getColor("Tree.selectionForeground")); + } else { + editorComponent.setForeground(UIManager.getColor("Tree.selectionForegroundInactive")); + } + } return editorComponent; } } diff --git a/src/main/java/com/weis/darklaf/ui/tree/DarkTreeCellRenderer.java b/src/main/java/com/weis/darklaf/ui/tree/DarkTreeCellRenderer.java index 13915c17..00757ee8 100644 --- a/src/main/java/com/weis/darklaf/ui/tree/DarkTreeCellRenderer.java +++ b/src/main/java/com/weis/darklaf/ui/tree/DarkTreeCellRenderer.java @@ -24,6 +24,7 @@ package com.weis.darklaf.ui.tree; import com.weis.darklaf.ui.cell.DarkCellRendererToggleButton; +import com.weis.darklaf.util.DarkUIUtil; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -58,8 +59,11 @@ public class DarkTreeCellRenderer extends DefaultTreeCellRenderer implements Tre rendererComponent.setRenderComponent(comp); return rendererComponent; } - - return super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); + var comp = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); + if (sel && !DarkUIUtil.hasFocus(tree)) { + comp.setForeground(UIManager.getColor("Tree.selectionForegroundInactive")); + } + return comp; } public static Object unwrapBooleanIfPossible(final Object value) { diff --git a/src/main/resources/com/weis/darklaf/properties/ui/list.properties b/src/main/resources/com/weis/darklaf/properties/ui/list.properties index 2e6be4cd..9518e1a8 100644 --- a/src/main/resources/com/weis/darklaf/properties/ui/list.properties +++ b/src/main/resources/com/weis/darklaf/properties/ui/list.properties @@ -30,4 +30,5 @@ List.cellNoFocusBorder = com.weis.darklaf.ui.list.DarkListCellBor List.dropLineColor = %dropForeground List.selectionBackground = %highlightFillFocus List.focusBorderColor = %borderFocus -List.alternateRowBackground = %backgroundAlternative \ No newline at end of file +List.alternateRowBackground = %backgroundAlternative +List.selectionForegroundInactive = %textSelectionForegroundInactive diff --git a/src/main/resources/com/weis/darklaf/properties/ui/table.properties b/src/main/resources/com/weis/darklaf/properties/ui/table.properties index 82ff10b5..7f87a712 100644 --- a/src/main/resources/com/weis/darklaf/properties/ui/table.properties +++ b/src/main/resources/com/weis/darklaf/properties/ui/table.properties @@ -48,6 +48,7 @@ Table.focusCellBackground = %backgroundContainer Table.focusCellForeground = %textForeground Table.selectionNoFocusBackground = %highlightFill Table.selectionBackground = %highlightFillFocus +Table.selectionForegroundInactive = %textSelectionForegroundInactive Table.alternateRowColor = false Table.alternateRowBackground = %backgroundAlternative diff --git a/src/main/resources/com/weis/darklaf/properties/ui/tree.properties b/src/main/resources/com/weis/darklaf/properties/ui/tree.properties index 1316742a..c77a6bd4 100644 --- a/src/main/resources/com/weis/darklaf/properties/ui/tree.properties +++ b/src/main/resources/com/weis/darklaf/properties/ui/tree.properties @@ -35,6 +35,8 @@ Tree.lineFocusSelected = %borderFocus Tree.lineSelected = %gridLine Tree.lineUnselected = %gridLine +Tree.selectionForegroundInactive = %textSelectionForegroundInactive + Tree.lineTypeDashed = false Tree.textBackground = %textBackground Tree.rowHeight = 22 diff --git a/src/main/resources/com/weis/darklaf/theme/intellij/intellij_defaults.properties b/src/main/resources/com/weis/darklaf/theme/intellij/intellij_defaults.properties index f138cc4c..fe398072 100644 --- a/src/main/resources/com/weis/darklaf/theme/intellij/intellij_defaults.properties +++ b/src/main/resources/com/weis/darklaf/theme/intellij/intellij_defaults.properties @@ -108,7 +108,7 @@ %acceleratorForeground = 505050 %textSelectionForeground = f0f0f0 -%textSelectionForegroundInactive = f0f0f0 +%textSelectionForegroundInactive = 000000 %textSelectionBackground = 5974AB #currentLineBackground %textSelectionBackgroundSecondary = FCFAED diff --git a/src/test/java/TabFrameDemo.java b/src/test/java/TabFrameDemo.java index 0937e933..1670021f 100644 --- a/src/test/java/TabFrameDemo.java +++ b/src/test/java/TabFrameDemo.java @@ -1,11 +1,13 @@ import com.weis.darklaf.LafManager; import com.weis.darklaf.components.OverlayScrollPane; +import com.weis.darklaf.components.SelectableTreeNode; import com.weis.darklaf.components.alignment.Alignment; import com.weis.darklaf.components.tabframe.JTabFrame; import com.weis.darklaf.components.tabframe.TabbedPopup; import com.weis.darklaf.icons.IconLoader; import javax.swing.*; +import javax.swing.tree.DefaultMutableTreeNode; import java.awt.*; /* @@ -61,6 +63,7 @@ public class TabFrameDemo { panel.add(label); tabbedPopup.getTabbedPane().addTab("Tab " + i, panel); } + tabFrame.setComponentAt(new JScrollPane(createTree()), Alignment.NORTH_WEST, 0); /* Activate for custom tab demo. tabFrame.setUserTabComponentAt(new JLabel("NORTH (custom tab)") {{ setBorder(new EmptyBorder(0, 5, 0, 5)); @@ -86,4 +89,28 @@ public class TabFrameDemo { frame.setVisible(true); }); } + + protected static JTree createTree() { + DefaultMutableTreeNode root = new DefaultMutableTreeNode("States"); + DefaultMutableTreeNode parent1 = new DefaultMutableTreeNode("Andhra Pradesh"); + DefaultMutableTreeNode child = new DefaultMutableTreeNode("Vijayawada"); + DefaultMutableTreeNode child1 = new SelectableTreeNode("This node can be selected", true); + DefaultMutableTreeNode parent2 = new DefaultMutableTreeNode("Telangana"); + DefaultMutableTreeNode child2 = new DefaultMutableTreeNode("Hyderabad"); + + // Adding child nodes to parent + parent1.add(child); + parent1.add(child1); + parent2.add(child2); + + // Adding parent nodes to root + root.add(parent1); + root.add(parent2); + + // Adding root to JTree + JTree tree = new JTree(root); + tree.setEditable(true); +// tree.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); + return tree; + } } diff --git a/src/test/java/TabbedPaneDemo.java b/src/test/java/TabbedPaneDemo.java index 999a8e61..5b18cc76 100644 --- a/src/test/java/TabbedPaneDemo.java +++ b/src/test/java/TabbedPaneDemo.java @@ -13,7 +13,7 @@ public class TabbedPaneDemo extends JFrame { SwingUtilities.invokeLater(() -> { LafManager.install(); final JFrame frame = new JFrame(); - int tabCount = 1; + int tabCount = 2; frame.setSize(500 * tabCount, 500); var c = new JPanel(new GridLayout(1, 2)); for (int j = 0; j < tabCount; j++) { @@ -21,7 +21,7 @@ public class TabbedPaneDemo extends JFrame { final var tabbedPane = new ClosableTabbedPane(); tabbedPane.setName("TabPane " + j); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < j; i++) { var editor = new JTextPane(); editor.setText("TabPaneDemo TabPane-" + j + "\n".repeat(i + 1)); tabbedPane.addTab("Tab (" + i + "," + j + ")", editor); @@ -36,6 +36,8 @@ public class TabbedPaneDemo extends JFrame { tabbedPane.putClientProperty("JTabbedPane.southComponent", new Label("South")); tabbedPane.putClientProperty("JTabbedPane.westComponent", new Label("West")); + tabbedPane.setSelectedIndex(-1); + p.add(tabbedPane, BorderLayout.CENTER); p.add(new JPanel() {{ setLayout(new FlowLayout(FlowLayout.LEFT));