Browse Source

Added TabbedPaneUI.

pull/1/head
weisj 5 years ago
parent
commit
bca6c2f146
  1. 21
      darklaf.iml
  2. 2
      src/main/java/com/weis/darklaf/DarkLaf.java
  3. 2
      src/main/java/com/weis/darklaf/LafManager.java
  4. 6
      src/main/java/com/weis/darklaf/components/ScrollPopupMenu.java
  5. 2
      src/main/java/com/weis/darklaf/icons/IconLoader.java
  6. 2
      src/main/java/com/weis/darklaf/ui/button/DarkButtonBorder.java
  7. 89
      src/main/java/com/weis/darklaf/ui/button/DarkButtonUI.java
  8. 160
      src/main/java/com/weis/darklaf/ui/button/DarkToggleButtonUI.java
  9. 8
      src/main/java/com/weis/darklaf/ui/scrollpane/DarkScrollBarUI.java
  10. 15
      src/main/java/com/weis/darklaf/ui/scrollpane/DarkScrollPaneUI.java
  11. 1767
      src/main/java/com/weis/darklaf/ui/tabbedpane/DarkTabbedPaneUI.java
  12. 1620
      src/main/java/com/weis/darklaf/ui/tabbedpane/DarkTabbedPaneUIBridge.java
  13. 655
      src/main/java/com/weis/darklaf/ui/tabbedpane/TabbedPaneTransferHandler.java
  14. 4
      src/main/java/com/weis/darklaf/ui/text/DarkCaret.java
  15. 21
      src/main/java/com/weis/darklaf/ui/text/DarkTextFieldUI.java
  16. 1
      src/main/java/com/weis/darklaf/util/DarkUIUtil.java
  17. 63
      src/main/java/com/weis/darklaf/util/ImageUtil.java
  18. 84
      src/main/resources/com/weis/darklaf/darcula.properties
  19. 96
      src/test/java/DnDTest.java
  20. 5
      src/test/java/ScrollPaneDemo.java
  21. 100
      src/test/java/TabbedPaneDemo.java
  22. 10
      src/test/java/UIDemo.java

21
darklaf.iml

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_12_PREVIEW">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: darcula:darcula.laf:1.0.0" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.swinglabs:swingx:1.6.1" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: com.jhlabs:filters:2.0.235" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.swinglabs:swing-worker:1.1" level="project" />
<orderEntry type="library" name="Maven: com.kitfox.svg:svg-salamander:1.0" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains:annotations:16.0.1" level="project" />
</component>
</module>

2
src/main/java/com/weis/darklaf/DarkLaf.java

@ -161,7 +161,7 @@ public class DarkLaf extends BasicLookAndFeel {
Properties properties = LafUtil.loadProperties(this);
final HashMap<String, Object> darculaGlobalSettings = new HashMap<>();
final String prefix = getPrefix();
final String prefix = getPrefix() + '.';
for (final String key : properties.stringPropertyNames()) {
if (key.startsWith(prefix)) {
darculaGlobalSettings

2
src/main/java/com/weis/darklaf/LafManager.java

@ -16,7 +16,7 @@ import java.awt.*;
*/
public final class LafManager {
private static Theme currentLaf;
private static Theme currentLaf = Theme.Dark;
static void setCurrentLaf(final Theme currentLaf) {
LafManager.currentLaf = currentLaf;

6
src/main/java/com/weis/darklaf/components/ScrollPopupMenu.java

@ -34,7 +34,7 @@ public class ScrollPopupMenu extends JPopupMenu {
}
};
private final int maxHeight;
private int maxHeight;
private final JPanel contentPane;
private final JScrollPane scrollPane;
private JWindow popWin;
@ -52,6 +52,10 @@ public class ScrollPopupMenu extends JPopupMenu {
addMenuKeyListener(menuKeyListener);
}
public void setMaxHeight(final int maxHeight) {
this.maxHeight = maxHeight;
}
@NotNull
private OverlayScrollPane createScrollPane() {
var view = new JPanel(new BorderLayout());

2
src/main/java/com/weis/darklaf/icons/IconLoader.java

@ -159,7 +159,7 @@ public final class IconLoader {
if (imgURL != null) {
return new ImageIcon(imgURL, description);
} else {
System.err.println("Couldn't find file: " + path);
LOGGER.severe("Could not find icon file: '" + path + "'");
return null;
}
}

2
src/main/java/com/weis/darklaf/ui/button/DarkButtonBorder.java

@ -28,7 +28,7 @@ public class DarkButtonBorder implements Border, UIResource {
@Override
public void paintBorder(final Component c, @NotNull final Graphics g,
final int x, final int y, final int width, final int height) {
if (DarkButtonUI.isShadowVariant(c)) {
if (DarkButtonUI.isShadowVariant(c) || DarkButtonUI.isLabelButton(c)) {
return;
}
Graphics2D g2 = (Graphics2D) g;

89
src/main/java/com/weis/darklaf/ui/button/DarkButtonUI.java

@ -12,8 +12,12 @@ import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicButtonListener;
import javax.swing.plaf.basic.BasicButtonUI;
import javax.swing.plaf.basic.BasicHTML;
import javax.swing.text.View;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
/**
* Custom adaption of {@link DarculaButtonUI}.
@ -25,6 +29,11 @@ public class DarkButtonUI extends BasicButtonUI {
public static final int SQUARE_ARC_SIZE = 3;
public static final int ARC_SIZE = 5;
protected static final Rectangle viewRect = new Rectangle();
protected static final Rectangle textRect = new Rectangle();
protected static final Rectangle iconRect = new Rectangle();
protected AbstractButton button;
private BasicButtonListener listener;
@NotNull
@Contract(value = "_ -> new", pure = true)
@ -33,9 +42,74 @@ public class DarkButtonUI extends BasicButtonUI {
}
@Override
public void paint(final Graphics g, @NotNull final JComponent c) {
public void installUI(final JComponent c) {
button = (AbstractButton) c;
super.installUI(c);
}
@Override
public boolean contains(@NotNull final JComponent c, final int x, final int y) {
if (!(x >= 0 && x <= c.getWidth() && y >= 0 && y <= c.getHeight())) return false;
int bs = DarkButtonBorder.BORDER_SIZE;
return new RoundRectangle2D.Float(bs, bs, c.getWidth() - 2 * bs, c.getWidth() - 2 * bs, getArcSize(c),
getArcSize(c)).contains(x, y);
}
@Override
public void paint(final Graphics g, final JComponent c) {
GraphicsContext config = new GraphicsContext(g);
AbstractButton b = (AbstractButton) c;
paintButton(g, c);
String text = layout(b, c, SwingUtilities2.getFontMetrics(b, g),
b.getWidth(), b.getHeight());
paintIcon(g, b, c);
paintText(g, b, c, text);
config.restore();
}
protected String layout(@NotNull final AbstractButton b, final JComponent c, final FontMetrics fm,
final int width, final int height) {
Insets i = b.getInsets();
viewRect.x = i.left;
viewRect.y = i.top;
viewRect.width = width - (i.right + viewRect.x);
viewRect.height = height - (i.bottom + viewRect.y);
textRect.x = textRect.y = textRect.width = textRect.height = 0;
iconRect.x = iconRect.y = iconRect.width = iconRect.height = 0;
// layout the text and icon
return SwingUtilities.layoutCompoundLabel(
b, fm, b.getText(), b.getIcon(),
b.getVerticalAlignment(), b.getHorizontalAlignment(),
b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
viewRect, iconRect, textRect,
b.getText() == null ? 0 : b.getIconTextGap());
}
protected void paintText(final Graphics g, final AbstractButton b, final JComponent c, final String text) {
GraphicsUtil.setupAAPainting(g);
if (text != null && !text.equals("")) {
View v = (View) c.getClientProperty(BasicHTML.propertyKey);
if (v != null) {
v.paint(g, textRect);
} else {
paintText(g, b, textRect, text);
}
}
}
protected void paintIcon(final Graphics g, @NotNull final AbstractButton b, final JComponent c) {
if (b.getIcon() != null) {
paintIcon(g, c, iconRect);
}
}
protected void paintButton(final Graphics g, @NotNull final JComponent c) {
Graphics2D g2 = (Graphics2D) g;
GraphicsContext config = new GraphicsContext(g2);
int borderSize = DarkButtonBorder.BORDER_SIZE;
if (shouldDrawBackground(c)) {
int arc = getArcSize(c);
@ -58,8 +132,6 @@ public class DarkButtonUI extends BasicButtonUI {
}
}
}
config.restore();
super.paint(g2, c);
}
protected int getArcSize(final JComponent c) {
@ -128,9 +200,10 @@ public class DarkButtonUI extends BasicButtonUI {
}
private boolean shouldDrawBackground(@NotNull final JComponent c) {
if (isLabelButton(c)) return false;
AbstractButton button = (AbstractButton) c;
Border border = c.getBorder();
return c.isEnabled() && border != null && button.isContentAreaFilled() && !(c instanceof JToggleButton);
return c.isEnabled() && border != null && button.isContentAreaFilled();
}
@Contract("null -> false")
@ -150,6 +223,12 @@ public class DarkButtonUI extends BasicButtonUI {
&& Boolean.TRUE.equals(((JButton) c).getClientProperty("JButton.forceRoundCorner"));
}
@Contract("null -> false")
public static boolean isLabelButton(final Component c) {
return c instanceof JButton
&& "onlyLabel".equals(((JButton) c).getClientProperty("JButton.variant"));
}
protected Color getForeground(@NotNull final AbstractButton button) {
Color fg = button.getForeground();
if (fg instanceof UIResource && button instanceof JButton && ((JButton) button).isDefaultButton()) {

160
src/main/java/com/weis/darklaf/ui/button/DarkToggleButtonUI.java

@ -1,26 +1,176 @@
package com.weis.darklaf.ui.button;
import com.weis.darklaf.util.DarkUIUtil;
import com.weis.darklaf.util.GraphicsContext;
import com.weis.darklaf.util.GraphicsUtil;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import sun.swing.SwingUtilities2;
import javax.swing.*;
import javax.swing.plaf.ComponentUI;
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.geom.RoundRectangle2D;
import java.beans.PropertyChangeListener;
public class DarkToggleButtonUI extends DarkButtonUI {
private static final int SLIDER_HEIGHT = 17;
private static final int SLIDER_WIDTH = 35;
private static Rectangle rect = new Rectangle();
private final PropertyChangeListener propertyChangeListener = evt -> {
if ("ToggleButton.variant".equals(evt.getPropertyName())) {
var oldVal = evt.getOldValue();
var newVal = evt.getNewValue();
if (oldVal != null && oldVal.equals(newVal)) {
return;
}
if ("slider".equals(newVal)) {
button.setBorderPainted(false);
} else {
button.setBorderPainted(true);
}
}
};
@NotNull
@Contract(value = "_ -> new", pure = true)
public static ComponentUI createUI(final JComponent c) {
return new DarkToggleButtonUI();
}
@Override
protected void installListeners(final AbstractButton b) {
super.installListeners(b);
button.addPropertyChangeListener(propertyChangeListener);
}
@Override
protected void uninstallListeners(final AbstractButton b) {
super.uninstallListeners(b);
button.removePropertyChangeListener(propertyChangeListener);
}
@Override
public boolean contains(@NotNull final JComponent c, final int x, final int y) {
if (!(x >= 0 && x <= c.getWidth() && y >= 0 && y <= c.getHeight())) return false;
var bounds = getSliderBounds(c);
return new RoundRectangle2D.Float(bounds.x, bounds.y, bounds.width, bounds.height,
bounds.height, bounds.height).contains(x,y);
}
@Override
public void paint(final Graphics g, @NotNull final JComponent c) {
if (isSlider(c)) {
GraphicsContext config = GraphicsUtil.setupStrokePainting(g);
AbstractButton b = (AbstractButton) c;
String text = layout(b, c, SwingUtilities2.getFontMetrics(b, g),
b.getWidth(), b.getHeight());
paintSlider((Graphics2D) g, b);
paintIcon(g, b, c);
paintText(g, b, c, text);
config.restore();
} else {
super.paint(g, c);
}
}
private void paintSlider(@NotNull final Graphics2D g, final AbstractButton c) {
var bounds = getSliderBounds(c);
g.translate(bounds.x, bounds.y);
Shape slider = new RoundRectangle2D.Float(0, 0, bounds.width, bounds.height,
bounds.height, bounds.height);
g.setColor(getBackgroundColor(c));
g.fill(slider);
g.setColor(getToggleBorderColor(c));
g.draw(slider);
if (c.hasFocus()) {
var config = new GraphicsContext(g);
g.setComposite(DarkUIUtil.ALPHA_COMPOSITE);
g.translate(-2, -2);
DarkUIUtil.paintFocusBorder(g, bounds.width + 4, bounds.height + 4,
(float) (bounds.height / 2.0) + 2, true);
g.translate(2, 2);
config.restore();
}
g.setColor(getSliderColor(c));
if (c.isSelected()) {
g.fill(new Ellipse2D.Float(
bounds.width - bounds.height + 1, 1, bounds.height - 1.5f, bounds.height - 1.5f));
} else {
g.fill(new Ellipse2D.Float(1, 1, bounds.height - 1.5f, bounds.height - 1.5f));
}
g.translate(-bounds.x, -bounds.y);
}
private static Color getSliderColor(@NotNull final AbstractButton b) {
return b.isEnabled() ? UIManager.getColor("ToggleButton.sliderColor")
: UIManager.getColor("ToggleButton.disabledSliderColor");
}
private static Color getToggleBorderColor(@NotNull final AbstractButton b) {
return b.isEnabled() ? UIManager.getColor("ToggleButton.sliderBorderColor")
: UIManager.getColor("ToggleButton.disabledSliderBorderColor");
}
public Dimension getPreferredSize(final JComponent c) {
Dimension d = super.getPreferredSize(c);
d.width += SLIDER_WIDTH + DarkButtonBorder.BORDER_SIZE;
return d;
}
@Override
protected String layout(@NotNull final AbstractButton b, final JComponent c,
final FontMetrics fm, final int width, final int height) {
if (isSlider(c)) {
Insets i = b.getInsets();
var bounds = getSliderBounds(c);
viewRect.x = bounds.x + bounds.width + DarkButtonBorder.BORDER_SIZE;
viewRect.y = i.top;
viewRect.width = width - (i.right + viewRect.x);
viewRect.height = height - (i.bottom + viewRect.y);
textRect.x = textRect.y = textRect.width = textRect.height = 0;
iconRect.x = iconRect.y = iconRect.width = iconRect.height = 0;
// layout the text and icon
return SwingUtilities.layoutCompoundLabel(
b, fm, b.getText(), b.getIcon(),
b.getVerticalAlignment(), b.getHorizontalAlignment(),
b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
viewRect, iconRect, textRect,
b.getText() == null ? 0 : b.getIconTextGap());
} else {
return super.layout(b, c, fm, width, height);
}
}
@NotNull
private Rectangle getSliderBounds(@NotNull final JComponent c) {
int x = DarkButtonBorder.BORDER_SIZE;
int y = (c.getHeight() - SLIDER_HEIGHT) / 2;
rect.x = x;
rect.y = y;
rect.width = SLIDER_WIDTH;
rect.height = SLIDER_HEIGHT;
return rect;
}
@Contract("null -> false")
private static boolean isSlider(final JComponent c) {
return c instanceof JToggleButton
&& "slider".equals(c.getClientProperty("ToggleButton.variant"));
}
protected Color getBackgroundColor(@NotNull final JComponent c) {
return c.isEnabled() || (c instanceof JToggleButton && ((JToggleButton) c).isSelected())
? (c instanceof JButton && (((JButton) c).isDefaultButton()))
? UIManager.getColor("Button.darcula.defaultFillColor")
: UIManager.getColor("Button.darcula.activeFillColor")
: UIManager.getColor("Button.darcula.inactiveFillColor");
if ((c instanceof JToggleButton && ((JToggleButton) c).isSelected())) {
return UIManager.getColor("Button.darcula.activeFillColor");
} else {
return UIManager.getColor("Button.darcula.inactiveFillColor");
}
}
}

8
src/main/java/com/weis/darklaf/ui/scrollpane/DarkScrollBarUI.java

@ -42,8 +42,8 @@ public class DarkScrollBarUI extends BasicScrollBarUI {
&& !((JScrollPane) scrollbar.getParent()).isWheelScrollingEnabled()) {
return;
}
if (scrollbar.getOrientation() == VERTICAL && e.getModifiersEx() == 0
|| scrollbar.getOrientation() == HORIZONTAL && e.getModifiersEx() == KeyEvent.SHIFT_DOWN_MASK) {
if (scrollbar.getOrientation() == VERTICAL && !e.isShiftDown()
|| scrollbar.getOrientation() == HORIZONTAL && e.isShiftDown()) {
scrollbar.setValueIsAdjusting(true);
if (scrollbar.getParent() instanceof JScrollPane) {
doScroll(scrollbar, ((JScrollPane) scrollbar.getParent()).getViewport(), e,
@ -448,10 +448,10 @@ public class DarkScrollBarUI extends BasicScrollBarUI {
public static void doScroll(@NotNull final JScrollBar toScroll, final JViewport vp,
@NotNull final MouseWheelEvent e, final boolean leftToRight) {
int direction = e.getWheelRotation() < 0 ? -1 : 1;
if (!leftToRight) {
int orientation = toScroll.getOrientation();
if (!leftToRight && orientation == JScrollBar.HORIZONTAL) {
direction *= -1;
}
int orientation = toScroll.getOrientation();
if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) {
int units = Math.abs(e.getUnitsToScroll());

15
src/main/java/com/weis/darklaf/ui/scrollpane/DarkScrollPaneUI.java

@ -7,7 +7,6 @@ import javax.swing.*;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicScrollPaneUI;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.MouseWheelListener;
import java.beans.PropertyChangeListener;
@ -25,8 +24,7 @@ public class DarkScrollPaneUI extends BasicScrollPaneUI {
scrollbar.setValueIsAdjusting(false);
};
private final MouseWheelListener horizontalMouseWheelListener = e -> {
if (!scrollpane.isWheelScrollingEnabled() ||
e.getModifiersEx() == KeyEvent.SHIFT_DOWN_MASK || !verticalScrollBarEnabled()) {
if (!scrollpane.isWheelScrollingEnabled() || e.isShiftDown() || !verticalScrollBarEnabled()) {
return;
}
var scrollbar = scrollpane.getVerticalScrollBar();
@ -39,8 +37,8 @@ public class DarkScrollPaneUI extends BasicScrollPaneUI {
if (!scrollpane.isWheelScrollingEnabled()) {
return;
}
var scrollbar = e.getModifiersEx() == KeyEvent.SHIFT_DOWN_MASK ? scrollpane.getHorizontalScrollBar()
: scrollpane.getVerticalScrollBar();
var scrollbar = e.isShiftDown() ? scrollpane.getHorizontalScrollBar()
: scrollpane.getVerticalScrollBar();
scrollbar.setValueIsAdjusting(true);
DarkScrollBarUI.doScroll(scrollbar, scrollpane.getViewport(), e,
scrollpane.getComponentOrientation().isLeftToRight());
@ -118,6 +116,13 @@ public class DarkScrollPaneUI extends BasicScrollPaneUI {
vertBounds.height += horBounds.height;
}
}
Insets barInsets = UIManager.getInsets("ScrollPane.barInsets");
if (barInsets != null) {
vertBounds.height -= barInsets.top + barInsets.bottom;
vertBounds.y += barInsets.top;
horBounds.width -= barInsets.left + barInsets.right;
horBounds.x += barInsets.left;
}
vsb.setBounds(vertBounds);
hsb.setBounds(horBounds);
}

1767
src/main/java/com/weis/darklaf/ui/tabbedpane/DarkTabbedPaneUI.java

File diff suppressed because it is too large Load Diff

1620
src/main/java/com/weis/darklaf/ui/tabbedpane/DarkTabbedPaneUIBridge.java

File diff suppressed because it is too large Load Diff

655
src/main/java/com/weis/darklaf/ui/tabbedpane/TabbedPaneTransferHandler.java

@ -0,0 +1,655 @@
package com.weis.darklaf.ui.tabbedpane;
import com.weis.darklaf.util.ImageUtil;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragGestureRecognizer;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceContext;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
public class TabbedPaneTransferHandler extends TransferHandler implements DropTargetListener, SwingConstants {
private static final String MIME_TYPE = DataFlavor.javaJVMLocalObjectMimeType + ";class=javax.swing.JTabbedPane";
private static final Rectangle EMPTY_RECT = new Rectangle(0, 0, 0, 0);
private static TabbedPaneDragGestureRecognizer recognizer = null;
private int lastTab = -1;
private DataFlavor tabFlavor;
/**
* The location of the mouse cursor throughout the drag-and-drop.
* This is here because of a deficiency in TransferHandler's design; you
* have no way of knowing the exact drop location in the component with a
* plain TransferHandler unless you implement DropTargetListener and get
* it that way.
*/
protected Point mouseLocation;
private TabTransferable currentTransferable;
public TabbedPaneTransferHandler() {
try {
tabFlavor = new DataFlavor(MIME_TYPE);
} catch (ClassNotFoundException ignored) {
}
}
public void exportAsDrag(final JComponent comp, final InputEvent e, final int a) {
int srcActions = getSourceActions(comp);
int action = a;
// only mouse events supported for drag operations
if (!(e instanceof MouseEvent)
// only support known actions
|| !(action == COPY || action == MOVE || action == LINK)
// only support valid source actions
|| (srcActions & action) == 0) {
action = NONE;
}
if (action != NONE && !GraphicsEnvironment.isHeadless()) {
if (recognizer == null) {
recognizer = new TabbedPaneDragGestureRecognizer(new TabbedPaneDragHandler());
}
recognizer.gestured(comp, (MouseEvent) e, srcActions, action);
} else {
exportDone(comp, null, NONE);
}
}
/**
* Overridden to include a check for a TabData flavor.
*/
@Override
public boolean canImport(final JComponent c, final DataFlavor[] flavors) {
return hasTabFlavor(flavors);
}
@Override
protected Transferable createTransferable(final JComponent c) {
JTabbedPane tabPane = (JTabbedPane) c;
currentTransferable = new TabTransferable(tabPane);
var ui = supportsIndicator(c);
int index = currentTransferable.transferData.tabIndex;
if (tabPane.getTabCount() > 1) {
if (index == 0) {
index++;
} else {
index--;
}
} else {
index = -1;
}
tabPane.setSelectedIndex(index);
if (ui != null) {
ui.setRolloverTab(-1);
createDragImage(tabPane, ui);
ui.setSourceIndicator(currentTransferable.transferData.tabIndex);
} else {
createDragImage(tabPane, null);
}
if ((ui != null && !ui.scrollableTabLayoutEnabled())
|| tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT) {
tabPane.setSelectedIndex(currentTransferable.transferData.tabIndex);
}
return currentTransferable;
}
protected void createDragImage(@NotNull final JTabbedPane tabbedPane, final DarkTabbedPaneUI ui) {
Image tabImage = ImageUtil.imageFromComponent(tabbedPane, currentTransferable.transferData.tabBounds);
int w = tabImage.getWidth(null);
int h = tabImage.getHeight(null);
var g = tabImage.getGraphics();
if (ui != null) {
g.setColor(ui.getDragBorderColor());
} else {
g.setColor(tabbedPane.getBackgroundAt(currentTransferable.transferData.tabIndex).brighter());
}
int lw = 2;
g.fillRect(0, 0, w, lw);
g.fillRect(0, 0, lw, h);
g.fillRect(w - lw, 0, lw, h);
g.fillRect(0, h - lw, w, lw);
g.dispose();
setDragImageOffset(new Point(w / 2, h / 2));
setDragImage(tabImage);
}
@Override
public void dragEnter(final DropTargetDragEvent e) {
}
@Override
public void dragExit(@NotNull final DropTargetEvent e) {
Component c = e.getDropTargetContext().getComponent();
lastTab = -1;
var ui = supportsIndicator(c);
if (ui != null) {
ui.clearDropIndicator();
}
}
@Contract("null -> null")
private DarkTabbedPaneUI supportsIndicator(final Component c) {
if (c instanceof JComponent && ((JComponent) c).getUI() instanceof DarkTabbedPaneUI) {
return ((DarkTabbedPaneUI) ((JComponent) c).getUI());
}
return null;
}
@Override
public void dragOver(@NotNull final DropTargetDragEvent e) {
e.getDropTargetContext().getComponent().setCursor(Cursor.getDefaultCursor());
mouseLocation = e.getLocation();
Component c = e.getDropTargetContext().getComponent();
JTabbedPane destTabbedPane = (JTabbedPane) c;
var ui = supportsIndicator(destTabbedPane);
if (ui != null) {
TabTransferable t = currentTransferable;
if (t != null) {
int tab = getDroppedTabIndex(t, destTabbedPane, mouseLocation);
if (tab == -1) {
lastTab = tab;
ui.clearDropIndicator();
return;
}
int tabPlacement = destTabbedPane.getTabPlacement();
Rectangle dropRect = t.getTabBounds();
Rectangle destRect = destTabbedPane.getBoundsAt(Math.min(tab, destTabbedPane.getTabCount() - 1));
JTabbedPane source = t.transferData.sourceTabbedPane;
int sourceIndex = t.transferData.tabIndex;
if (ui.scrollableTabLayoutEnabled()) {
boolean lastInSource = false;
if (destTabbedPane == source && (tab == sourceIndex || (sourceIndex == source.getTabCount() - 1
&& tab == source.getTabCount()))) {
lastInSource = true;
destRect.width = dropRect.width;
destRect.height = dropRect.height;
}
switch (tabPlacement) {
case TOP, BOTTOM -> {
if (destTabbedPane.getComponentOrientation().isLeftToRight()) {
if (tab >= destTabbedPane.getTabCount() && !lastInSource) {
destRect.x += destRect.width;
}
dropRect.x = destRect.x;
if (lastTab != -1 && lastTab < tab) {
dropRect.x -= dropRect.width;
}
} else {
if (tab >= destTabbedPane.getTabCount()) {
destRect.x -= 2 * dropRect.width;
if (lastTab < tab) {
destRect.x += destRect.width;
}
}
dropRect.x = destRect.x + dropRect.width;
if (lastTab != -1 && lastTab > tab) {
dropRect.x -= dropRect.width;
}
}
dropRect.y = destRect.y + destRect.height - dropRect.height;
}
case LEFT, RIGHT -> {
if (tab >= destTabbedPane.getTabCount()) {
destRect.y += destRect.height;
}
dropRect.y = destRect.y;
dropRect.x = destRect.x + destRect.width - dropRect.width;
if (lastTab != -1 && lastTab < tab) {
dropRect.y -= dropRect.height;
}
}
}
} else {
if (source == destTabbedPane && (tab == sourceIndex || tab == sourceIndex + 1)) {
dropRect.setRect(0, 0, 0, 0);
} else {
switch (destTabbedPane.getTabPlacement()) {
case TOP, BOTTOM -> {
var b = ui.getTabAreaBounds();
if (tab == destTabbedPane.getTabCount()) {
dropRect.x = destRect.x + destRect.width / 2;
dropRect.width = Math.min(b.x + b.width - dropRect.x, dropRect.width);
} else if (tab == 0) {
dropRect.x = destRect.x;
dropRect.width = Math.min(dropRect.width / 2, destRect.width / 2);
} else {
var prev = destTabbedPane.getBoundsAt(tab - 1);
if (destRect.y + destRect.height <= mouseLocation.y &&
prev.y <= mouseLocation.y && mouseLocation.y <= prev.y + prev.height) {
destRect.x = prev.x + prev.width;
destRect.y = prev.y;
destRect.height = prev.height;
}
dropRect.x = destRect.x;
dropRect.setLocation(destRect.getLocation());
dropRect.x -= dropRect.width / 2;
if (dropRect.x < b.x) {
int diff = b.x - dropRect.x;
dropRect.width -= diff;
dropRect.x = b.x;
}
if (dropRect.x + dropRect.width > b.x + b.width) {
int diff = dropRect.width + dropRect.x - b.width - b.x;
dropRect.width -= diff;
}
}
dropRect.y = destRect.y + destRect.height - dropRect.height;
}
case LEFT, RIGHT -> {
}
}
}
}
ui.setDnDIndicatorRect(dropRect.x, dropRect.y, dropRect.width, dropRect.height,
tab, source == destTabbedPane);
lastTab = tab;
}
}
}
@Override
public void drop(@NotNull final DropTargetDropEvent e) {
Component c = e.getDropTargetContext().getComponent();
var ui = supportsIndicator(c);
if (ui != null) {
ui.clearDropIndicator();
}
}
@Override
public void dropActionChanged(final DropTargetDragEvent e) {
}
/**
* Returns the index at which to add a tab if it is dropped at the mouse
* location specified by <code>p</code>.
*
* @param tabbedPane The tabbed pane who would be receiving the tab.
* @param p The mouse location.
* @return The index at which to add the tab.
*/
protected int getDroppedTabIndex(final TabTransferable t, @NotNull final JTabbedPane tabbedPane,
@NotNull final Point p) {
var tab = tabbedPane.indexAtLocation(p.x, p.y);
var ui = supportsIndicator(tabbedPane);
if (ui != null) {
if (tab == -1) {
var bounds = ui.getTabAreaBounds();
if (bounds.contains(p)) {
if (tabbedPane.getTabCount() > 0) {
var minb = ui.getTabBounds(tabbedPane, 0);
var maxb = ui.getTabBounds(tabbedPane, tabbedPane.getTabCount() - 1);
if (tabbedPane.getComponentOrientation().isLeftToRight()) {
int x = Math.max(bounds.x, minb.x);
bounds.width = Math.min(bounds.x + bounds.width - x, maxb.x + maxb.width - x);
bounds.x = x;
} else {
int x = Math.max(bounds.x, maxb.x);
bounds.width = Math.min(bounds.x + bounds.width - x, minb.x + minb.width - x);
bounds.x = x;
}
int y = Math.max(bounds.y, minb.y);
bounds.height = Math.min(bounds.y + bounds.height - y, maxb.x + maxb.height - y);
}
switch (tabbedPane.getTabPlacement()) {
case TOP, BOTTOM -> {
if (tabbedPane.getComponentOrientation().isLeftToRight()) {
tab = p.x <= bounds.x + bounds.width / 2 ? 0 : tabbedPane.getTabCount();
} else {
tab = p.x >= bounds.x + bounds.width / 2 ? 1 : tabbedPane.getTabCount();
}
}
case LEFT, RIGHT -> tab = p.y <= bounds.y + bounds.height / 2 ? 0 : tabbedPane.getTabCount();
}
}
} else {
if (tab < tabbedPane.getTabCount()) {
var b = tabbedPane.getBoundsAt(tab);
if (tab >= 1 && !ui.scrollableTabLayoutEnabled()) {
var prev = tabbedPane.getBoundsAt(tab - 1);
if (b.y + b.height < mouseLocation.y &&
prev.y <= mouseLocation.y && mouseLocation.y <= prev.y + prev.height) {
b = prev;
}
}
var sb = (ui.scrollableTabLayoutEnabled()) ? t.getTabBounds() : EMPTY_RECT;
switch (tabbedPane.getTabPlacement()) {
case TOP, BOTTOM -> {
if (tabbedPane.getComponentOrientation().isLeftToRight()) {
if (p.x >= b.x + sb.width + (b.width - sb.width) / 2) {
tab += 1;
}
} else {
if (p.x <= b.x + (b.width - sb.width) / 2) {
tab += 1;
}
}
}
case LEFT, RIGHT -> {
if (p.y >= b.y + sb.height + (b.height - sb.height) / 2) {
tab += 1;
}
}
}
}
}
} else if (tab == -1) {
tab = tabbedPane.getTabCount();
}
return tab;
}
/**
* We can only move tabs, we cannot copy them.
*
* @param c This parameter is ignored.
* @return <code>TransferHandler.MOVE</code>, as we can only move tabs.
*/
@Override
public int getSourceActions(final JComponent c) {
return MOVE;
}
protected boolean hasTabFlavor(final DataFlavor[] flavors) {
if (tabFlavor == null) {
return false;
}
for (DataFlavor flavor : flavors) {
if (tabFlavor.equals(flavor)) {
return true;
}
}
return false;
}
/**
* Called when the drag-and-drop operation has just completed. This
* creates a new tab identical to the one "dragged" and places it in the
* destination <code>JTabbedPane</code>.
*
* @param c The component receiving the "drop" (the instance of
* <code>JTabbedPane</code>).
* @param t The data being transfered (information about the tab and the
* component contained by the tab).
* @return Whether or not the import was successful.
*/
@Override
public boolean importData(final JComponent c, @NotNull final Transferable t) {
boolean successful = false;
if (hasTabFlavor(t.getTransferDataFlavors()) && mouseLocation != null) {
try {
JTabbedPane tabbedPane = (JTabbedPane) c;
int tab = getDroppedTabIndex(currentTransferable, tabbedPane, mouseLocation);
TabTransferable.TabTransferData td = (TabTransferable.TabTransferData) t.getTransferData(tabFlavor);
JTabbedPane sourcePane = td.sourceTabbedPane;
int sourceIndex = td.tabIndex;
if (tabbedPane == sourcePane && sourceIndex == tab) {
//Nothing to do. Just select the tab to be sure.
selectTab(sourcePane, sourceIndex);
return true;
}
if (tab < 0 || tab > tabbedPane.getTabCount()) {
return false;
}
String tabName = sourcePane.getTitleAt(sourceIndex);
Icon icon = sourcePane.getIconAt(sourceIndex);
Component comp = sourcePane.getComponentAt(sourceIndex);
String toolTip = sourcePane.getToolTipTextAt(sourceIndex);
Color foreground = sourcePane.getForegroundAt(sourceIndex);
Component tabComp = sourcePane.getTabComponentAt(sourceIndex);
tabbedPane.insertTab(tabName, icon, comp, toolTip, tab);
int index = tab;
if (tabbedPane == sourcePane) {
if (sourceIndex < index) index--;
}
if (tabComp != null) {
tabbedPane.setTabComponentAt(index, tabComp);
}
tabbedPane.setForegroundAt(index, foreground);
selectTab(tabbedPane, index);
successful = true;
var ui = supportsIndicator(c);
if (ui != null) {
ui.clearDropIndicator();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return successful;
}
/**
* Selects the specified tab in the specified tabbed pane. This method
* can be overridden by subclasses to do more stuff than simply select
* the tab.
*
* @param tabbedPane The tabbed pane.
* @param index The index of the tab to select.
*/
protected void selectTab(final JTabbedPane tabbedPane, final int index) {
SwingUtilities.invokeLater(() -> {
tabbedPane.setSelectedIndex(index);
tabbedPane.requestFocus();
});
}
/**
* Transferable representing a tab from a tabbed pane and its contents.
*/
public class TabTransferable implements Transferable {
private final TabTransferData transferData;
/**
* The data remembered about the tab.
*/
public class TabTransferData {
private final JTabbedPane sourceTabbedPane;
private final int tabIndex;
private final Rectangle tabBounds;
@Contract(pure = true)
public TabTransferData(@NotNull final JTabbedPane tabbedPane, final int tabIndex) {
this.sourceTabbedPane = tabbedPane;
this.tabIndex = tabIndex;
this.tabBounds = tabbedPane.getBoundsAt(tabIndex);
}
}
public TabTransferable(@NotNull final JTabbedPane tabbedPane) {
int index = tabbedPane.getSelectedIndex();
transferData = new TabTransferData(tabbedPane, index);
}
public Rectangle getTabBounds() {
return new Rectangle(transferData.tabBounds);
}
@Override
public Object getTransferData(final DataFlavor flavor) throws UnsupportedFlavorException {
if (!isDataFlavorSupported(flavor)) {
throw new UnsupportedFlavorException(flavor);
}
return transferData;
}
@Override
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[]{tabFlavor};
}
@Override
public boolean isDataFlavorSupported(final DataFlavor flavor) {
return tabFlavor.equals(flavor);
}
}
protected class TabbedPaneDragHandler implements DragGestureListener, DragSourceListener {
private boolean scrolls;
// --- DragGestureListener methods -----------------------------------
/**
* a Drag gesture has been recognized
*/
public void dragGestureRecognized(@NotNull final DragGestureEvent dge) {
JComponent c = (JComponent) dge.getComponent();
TabbedPaneTransferHandler th = (TabbedPaneTransferHandler) c.getTransferHandler();
Transferable t = th.createTransferable(c);
if (t != null) {
scrolls = c.getAutoscrolls();
c.setAutoscrolls(false);
try {
Image im = th.getDragImage();
if (im == null) {
dge.startDrag(Cursor.getDefaultCursor(), t, this);
} else {
dge.startDrag(Cursor.getDefaultCursor(), im, th.getDragImageOffset(), t, this);
}
return;
} catch (RuntimeException re) {
c.setAutoscrolls(scrolls);
}
}
th.exportDone(c, t, NONE);
}
// --- DragSourceListener methods -----------------------------------
/**
* as the hotspot enters a platform dependent drop site
*/
public void dragEnter(final DragSourceDragEvent dsde) {
}
/**
* as the hotspot moves over a platform dependent drop site
*/
public void dragOver(final DragSourceDragEvent dsde) {
}
/**
* as the hotspot exits a platform dependent drop site
*/
public void dragExit(final DragSourceEvent dsde) {
}
/**
* as the operation completes
*/
public void dragDropEnd(@NotNull final DragSourceDropEvent dsde) {
DragSourceContext dsc = dsde.getDragSourceContext();
JComponent c = (JComponent) dsc.getComponent();
if (dsde.getDropSuccess()) {
((TabbedPaneTransferHandler) c.getTransferHandler()).exportDone(c, dsc.getTransferable(),
dsde.getDropAction());
} else {
((TabbedPaneTransferHandler) c.getTransferHandler()).exportDone(c, dsc.getTransferable(), NONE);
}
c.setAutoscrolls(scrolls);
var ui = supportsIndicator(currentTransferable.transferData.sourceTabbedPane);
if (ui != null) {
ui.clearSourceIndicator();
}
if (!dsde.getDropSuccess()) {
selectTab(currentTransferable.transferData.sourceTabbedPane,
currentTransferable.transferData.tabIndex);
}
currentTransferable = null;
}
public void dropActionChanged(final DragSourceDragEvent dsde) {
}
}
protected static class TabbedPaneDragGestureRecognizer extends DragGestureRecognizer {
protected TabbedPaneDragGestureRecognizer(final DragGestureListener dgl) {
super(DragSource.getDefaultDragSource(), null, NONE, dgl);
}
void gestured(final JComponent c, final MouseEvent e, final int srcActions, final int action) {
setComponent(c);
setSourceActions(srcActions);
appendEvent(e);
fireDragGestureRecognized(action, e.getPoint());
}
/**
* register this DragGestureRecognizer's Listeners with the Component
*/
protected void registerListeners() {
}
/**
* unregister this DragGestureRecognizer's Listeners with the Component
* <p>
* subclasses must override this method
*/
protected void unregisterListeners() {
}
}
}

4
src/main/java/com/weis/darklaf/ui/text/DarkCaret.java

@ -48,9 +48,9 @@ public class DarkCaret extends DefaultCaret implements UIResource {
}
private void adjustCaretLocation(@NotNull final MouseEvent e) {
if ((e.getModifiersEx() & ActionEvent.SHIFT_MASK) != 0 && getDot() != -1) {
if (e.isShiftDown() && getDot() != -1) {
moveCaret(e);
} else {
} else{
positionCaret(e);
}
}

21
src/main/java/com/weis/darklaf/ui/text/DarkTextFieldUI.java

@ -24,8 +24,10 @@ import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
public class DarkTextFieldUI extends DarkTextFieldUIBridge {
public class DarkTextFieldUI extends DarkTextFieldUIBridge implements PropertyChangeListener {
public static final int ARC_SIZE = 3;
public static final int SEARCH_ARC_SIZE = 5;
@ -61,7 +63,6 @@ public class DarkTextFieldUI extends DarkTextFieldUIBridge {
@Override
public void popupMenuWillBecomeInvisible(@NotNull final PopupMenuEvent e) {
lastSearchEvent = System.currentTimeMillis();
((JPopupMenu) e.getSource()).removePopupMenuListener(this);
}
};
@ -112,7 +113,6 @@ public class DarkTextFieldUI extends DarkTextFieldUIBridge {
if (lastSearchEvent == 0 || (System.currentTimeMillis() - lastSearchEvent) > 250) {
var menu = getSearchPopup(getComponent());
if (menu != null) {
menu.addPopupMenuListener(searchPopupListener);
menu.show(getComponent(), getSearchIconCoord().x, getComponent().getHeight());
}
}
@ -267,6 +267,21 @@ public class DarkTextFieldUI extends DarkTextFieldUIBridge {
return DarkCaret.CaretStyle.THICK_VERTICAL_LINE_STYLE;
}
@Override
public void propertyChange(final PropertyChangeEvent evt) {
String key = evt.getPropertyName();
if ("JTextField.Search.FindPopup".equals(key)) {
var oldVal = evt.getOldValue();
var newVal = evt.getNewValue();
if (oldVal instanceof JPopupMenu) {
((JPopupMenu)oldVal).removePopupMenuListener(searchPopupListener);
}
if (newVal instanceof JPopupMenu) {
((JPopupMenu)newVal).addPopupMenuListener(searchPopupListener);
}
}
}
private enum ClickAction {
CLEAR,
SEARCH_POPUP,

1
src/main/java/com/weis/darklaf/util/DarkUIUtil.java

@ -18,6 +18,7 @@ import java.awt.geom.RoundRectangle2D;
public final class DarkUIUtil {
public final static AlphaComposite ALPHA_COMPOSITE = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f);
public final static AlphaComposite ALPHA_COMPOSITE_2 = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f);
public final static AlphaComposite SHADOW_COMPOSITE = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f);
public static final boolean USE_QUARTZ = "true".equals(System.getProperty("apple.awt.graphics.UseQuartz"));

63
src/main/java/com/weis/darklaf/util/ImageUtil.java

@ -0,0 +1,63 @@
package com.weis.darklaf.util;
import com.weis.darklaf.LogFormatter;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.logging.ConsoleHandler;
import java.util.logging.Logger;
/**
* Image utilities.
*
* @author Jannis Weis
* @since 2018
*/
public final class ImageUtil {
/**
* The scaling factor.
*/
public static final double SCALE_X;
public static final double SCALE_Y;
private static final Logger LOGGER = Logger.getLogger(ImageUtil.class.getName());
static {
LOGGER.setUseParentHandlers(false);
ConsoleHandler handler = new ConsoleHandler();
handler.setFormatter(new LogFormatter());
LOGGER.addHandler(handler);
var mode = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode();
var screenSize = Toolkit.getDefaultToolkit().getScreenSize();
SCALE_X = mode.getWidth() / (double) screenSize.width;
SCALE_Y = mode.getHeight() / (double) screenSize.height;
LOGGER.info("Using screen scaling SCALE_X=" + SCALE_X + ", SCALE_Y=" + SCALE_Y);
}
@Contract(pure = true)
private ImageUtil() {
}
/**
* Create image from component.
*
* @param c the component.
* @param bounds the bounds inside the component to capture.
* @return image containing the captured area.
*/
@NotNull
public static Image imageFromComponent(@NotNull final Component c, @NotNull final Rectangle bounds) {
BufferedImage image = new BufferedImage((int) (SCALE_X * bounds.width), (int) (SCALE_Y * bounds.height),
BufferedImage.TYPE_INT_RGB);
final Graphics2D g2d = (Graphics2D) image.getGraphics();
g2d.scale(SCALE_Y, SCALE_Y);
g2d.translate(-bounds.x, -bounds.y);
c.printAll(g2d);
g2d.dispose();
return image;
}
}

84
src/main/resources/com/weis/darklaf/darcula.properties

@ -40,6 +40,7 @@ RadioButtonMenuItem.checkIcon = empty(16,16)
Table.ascendingSortIcon = navigation/arrowSplitCenterH.svg[aware]
Table.descendingSortIcon = navigation/arrowSplitCenterH.svg[aware]
FileView.fileIcon = files/general.svg[aware]
TabbedPane.newTab.icon = navigation/add.svg[aware]
InternalFrame.icon = frame/frame.svg[aware]
OptionPane.informationIcon = dialog/informationDialog.svg[aware](32,32)
@ -157,7 +158,7 @@ Border.line2 = 82888C
#ScrollPane
ScrollPaneUI = com.weis.darklaf.ui.scrollpane.DarkScrollPaneUI
ScrollPane.fillLowerCorner = true
ScrollPane.barInsets = 0,0,0,0
#Scrollbar (done)
ScrollBarUI = com.weis.darklaf.ui.scrollpane.DarkScrollBarUI
@ -169,15 +170,27 @@ Scrollbar.thumbBorderColor = 515151
#TabbedPane
TabbedPaneUI = com.weis.darklaf.ui.tabbedpane.DarkTabbedPaneUI
TabbedPane.tabInsets = 5,7,5,7
TabbedPane.highlight = 292b2d
TabbedPane.tabRunOverlay = 0
TabbedPane.light = 444444
TabbedPane.selected = 3c3f41
TabbedPane.selectHighlight = 3c3f41
TabbedPane.tabBorder = 323232
TabbedPane.accent = 747A80
TabbedPane.accentFocus = 4A88C7
TabbedPane.selected = 4E5254
TabbedPane.highlight = 27292A
TabbedPane.selectHighlight = 333537
TabbedPane.contentBorderInsets = 0,0,0,0
TabbedPane.darkShadow = 292b2d
TabbedPane.shadow = 3c3f41
TabbedPane.tabsOverlapBorder = true
TabbedPane.maxPopupHeight = 500
TabbedPane.dropFill = 4B4B4B
TabbedPane.dragBorderColor = C0C0C0
TabbedPane.tabsOpaque = true
TabbedPane.tabsOverlapBorder = false
TabbedPane.labelShift = 0
TabbedPane.selectedLabelShift = 0
TabbedPane.selectedTabPadInsets = 0,0,0,0
@ -269,7 +282,7 @@ Button.disabledText = 777777
Button.darcula.shadow = 000000
Button.darcula.selectedButtonForeground = bbbbbb
Button.darcula.activeBorderColor = 6B6B6B
Button.darcula.inactiveBorderColor = 6B6B6B
Button.darcula.inactiveBorderColor = 535353
Button.darcula.defaultBorderColor = 4C708C
Button.darcula.inactiveFillColor = 3C3F41
Button.darcula.defaultFillColor = 365880
@ -286,6 +299,10 @@ Button.shadow.click = 5C6164
ToggleButtonUI = com.weis.darklaf.ui.button.DarkToggleButtonUI
ToggleButton.border = com.weis.darklaf.ui.button.DarkButtonBorder
ToggleButton.sliderBorderColor = 6B6B6B
ToggleButton.disabledSliderBorderColor = 535353
ToggleButton.sliderColor = A7A7A7
ToggleButton.disabledSliderColor = 606060
#Slider (done...) [timeStampVariant]
SliderUI = com.weis.darklaf.ui.slider.DarkSliderUI
@ -330,4 +347,57 @@ InternalFrameTitlePane.darcula.selected.borderColorBottom = 313C4C
InternalFrameTitlePane.darcula.backgroundColor = 3A3D3F
InternalFrameTitlePane.darcula.selected.backgroundColor = 424D5F
InternalFrameTitlePane.darcula.buttonColor = 8B8B8B
InternalFrameTitlePane.darcula.hovered.buttonColor = A8A8A8
InternalFrameTitlePane.darcula.hovered.buttonColor = A8A8A8
###Custom###
#Misc
Button.separator = 5F5F5F
Focus.color = ff0000
#TabbedPane
DnDTabbedPaneUI = edu.kit.mima.gui.laf.DarkDnDTabbedPaneUI
EditorTabbedPaneUI = edu.kit.mima.gui.laf.DarkEditorTabbedPaneUI
DnDTabbedPane.selectionAccent = 40B6E0
DnDTabbedPane.selectedTab = 515658
DnDTabbedPane.dropColor = 4B4B4B
DnDTabbedPane.selectedTab2 = 343638
DnDTabbedPane.selectionAccentUnfocused = 787878
#Numbering
Numbering.foreground = 606366
Numbering.background = 313335
Numbering.selectedForeground = a3a3a3
Numbering.selectedBackground = 323232
Numbering.font = Monospaced-0-12
#Editor
Editor.selectedBackground = 323232
Editor.selection = 2852a0
Editor.breakpoint = 3a2323
Editor.mark = 2D71D2
Editor.vertLine = 515151
#TabFrame
TabFramePopup.background = 3c3f41
TabFramePopup.focus = 3B4754
TabFramePopup.borderColor = 323232
TabFrameTab.selected = 2D2F30
TabFrameTab.hover = 353739
TabFrameTab.selectedFontColor = ffffff
TabFrameTab.defaultForeground = bbbbbb
TabFrame.line = 515151
#Tooltip
Tooltip.background = 4B4D4D
Tooltip.borderColor = 5B5D5F
#Terminal
Terminal.background = 2b2b2b
#FileDialog
FileDialog.errorBorder = 73454B
FileDialog.error = 593D41

96
src/test/java/DnDTest.java

@ -0,0 +1,96 @@
import com.weis.darklaf.icons.IconLoader;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class DnDTest extends JFrame {
public DnDTest() {
initUI();
}
private void initUI() {
var icon1 = IconLoader.get().getUIAwareIcon("files/folder.svg");
var icon2 = IconLoader.get().getUIAwareIcon("files/text.svg");
var icon3 = IconLoader.get().getUIAwareIcon("files/unknown.svg");
var label1 = new JLabel(icon1, JLabel.CENTER);
var label2 = new JLabel(icon2, JLabel.CENTER);
var label3 = new JLabel(icon3, JLabel.CENTER);
var listener = new DragMouseAdapter();
label1.addMouseListener(listener);
label2.addMouseListener(listener);
label3.addMouseListener(listener);
var button = new JButton(icon2);
button.setFocusable(false);
label1.setTransferHandler(new TransferHandler("icon"));
label2.setTransferHandler(new TransferHandler("icon"));
label3.setTransferHandler(new TransferHandler("icon"));
button.setTransferHandler(new TransferHandler("icon"));
createLayout(label1, label2, label3, button);
setTitle("Icon Drag & Drop");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
private class DragMouseAdapter extends MouseAdapter {
public void mousePressed(MouseEvent e) {
var c = (JComponent) e.getSource();
var handler = c.getTransferHandler();
handler.exportAsDrag(c, e, TransferHandler.COPY);
}
}
private void createLayout(JComponent... arg) {
var pane = getContentPane();
var gl = new GroupLayout(pane);
pane.setLayout(gl);
gl.setAutoCreateContainerGaps(true);
gl.setAutoCreateGaps(true);
gl.setHorizontalGroup(gl.createParallelGroup(GroupLayout.Alignment.CENTER)
.addGroup(gl.createSequentialGroup()
.addComponent(arg[0])
.addGap(30)
.addComponent(arg[1])
.addGap(30)
.addComponent(arg[2])
)
.addComponent(arg[3], GroupLayout.DEFAULT_SIZE,
GroupLayout.DEFAULT_SIZE, Integer.MAX_VALUE)
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addGroup(gl.createParallelGroup()
.addComponent(arg[0])
.addComponent(arg[1])
.addComponent(arg[2]))
.addGap(30)
.addComponent(arg[3])
);
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
var ex = new DnDTest();
ex.setVisible(true);
});
}
}

5
src/test/java/ScrollPaneDemo.java

@ -1,5 +1,4 @@
import com.weis.darklaf.LafManager;
import com.weis.darklaf.components.OverlayScrollPane;
import org.jdesktop.swingx.MultiSplitLayout;
import javax.swing.*;
@ -16,7 +15,7 @@ public final class ScrollPaneDemo extends MultiSplitLayout {
LafManager.loadLaf(LafManager.Theme.Dark);
final var frame = new JFrame();
frame.setSize(500, 500);
var overlayScroll = new OverlayScrollPane(new JTextPane(){{
var overlayScroll = new JScrollPane(new JTextPane() {{
setText("orem ipsum dolor sit amet, consectetur adipiscing elit. In tempor quis nibh a semper. Nullam"
+ " auctor, erat non viverra commodo, libero orci aliquam quam, ac interdum nunc est sed "
+ "ligula. Aliquam vel velit non dolor accumsan blandit id eu metus. Aenean iaculis urna in "
@ -46,7 +45,7 @@ public final class ScrollPaneDemo extends MultiSplitLayout {
// setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
setFont(Font.getFont(Font.MONOSPACED));
}});
frame.setContentPane(new JPanel(new BorderLayout()){{
frame.setContentPane(new JPanel(new BorderLayout()) {{
add(overlayScroll, BorderLayout.CENTER);
}});
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

100
src/test/java/TabbedPaneDemo.java

@ -1,7 +1,10 @@
import com.weis.darklaf.LafManager;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.UIResource;
import java.awt.*;
import java.awt.event.ItemEvent;
public class TabbedPaneDemo extends JFrame {
@ -9,26 +12,95 @@ public class TabbedPaneDemo extends JFrame {
SwingUtilities.invokeLater(() -> {
LafManager.loadLaf(LafManager.Theme.Dark);
final JFrame frame = new JFrame();
frame.setSize(500, 500);
var p = new JPanel(new BorderLayout());
final var tabbedPane = new JTabbedPane();
for (int i = 0; i < 20; i++) {
var editor = new JTextPane();
editor.setText("mima.TabFrameDemo\n".repeat(i + 1));
tabbedPane.addTab("Tab number " + i, editor);
int tabCount = 2;
frame.setSize(500 * tabCount, 500);
var c = new JPanel(new GridLayout(1,2));
for (int j = 0; j < tabCount; j++) {
var p = new JPanel(new BorderLayout());
final var tabbedPane = new JTabbedPane();
tabbedPane.setName("TabPane " + j);
for (int i = 0; i < 3; i++) {
var editor = new JTextPane();
editor.setText("TabPaneDemo TabPane-" + j + "\n".repeat(i + 1));
tabbedPane.addTab("Tab (" + i + "," + j +")", editor);
}
tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
tabbedPane.putClientProperty("JTabbedPane.showNewTabButton", Boolean.TRUE);
tabbedPane.putClientProperty("JTabbedPane.dndEnabled", Boolean.TRUE);
tabbedPane.putClientProperty("JTabbedPane.trailingComponent", new Label("Trailing"));
tabbedPane.putClientProperty("JTabbedPane.leadingComponent", new Label("Leading"));
p.add(tabbedPane, BorderLayout.CENTER);
p.add(new JPanel() {{
setLayout(new FlowLayout(FlowLayout.LEFT));
add(new JComboBox<String>() {{
addItem("TOP");
addItem("BOTTOM");
addItem("LEFT");
addItem("RIGHT");
setEditable(false);
addItemListener(e -> {
if (e.getStateChange() == ItemEvent.SELECTED) {
if ("TOP".equals(e.getItem())) {
tabbedPane.setTabPlacement(JTabbedPane.TOP);
} else if ("BOTTOM".equals(e.getItem())) {
tabbedPane.setTabPlacement(JTabbedPane.BOTTOM);
} else if ("LEFT".equals(e.getItem())) {
tabbedPane.setTabPlacement(JTabbedPane.LEFT);
} else if ("RIGHT".equals(e.getItem())) {
tabbedPane.setTabPlacement(JTabbedPane.RIGHT);
}
tabbedPane.requestFocus();
}
});
}});
add(new JCheckBox("Scroll-layout enabled") {{
addActionListener(e -> {
if (tabbedPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT) {
tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
} else {
tabbedPane.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT);
}
});
setSelected(true);
}});
add(new JCheckBox("Left To Right") {{
addActionListener(e -> {
if (tabbedPane.getComponentOrientation().isLeftToRight()) {
tabbedPane.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
} else {
tabbedPane.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
}
});
setSelected(true);
}});
add(new JCheckBox("DnD enabled") {{
addActionListener(e -> {
if (tabbedPane.getDropTarget().isActive()) {
tabbedPane.putClientProperty("JTabbedPane.dndEnabled", Boolean.FALSE);
} else {
tabbedPane.putClientProperty("JTabbedPane.dndEnabled", Boolean.TRUE);
}
});
setSelected(true);
}});
}}, BorderLayout.SOUTH);
c.add(p);
}
// tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
p.add(tabbedPane, BorderLayout.CENTER);
p.add(new JPanel(){{
setLayout(new FlowLayout(FlowLayout.LEFT));
add(new JButton("Unfocus"));
}}, BorderLayout.SOUTH);
frame.setContentPane(p);
frame.setContentPane(c);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.repaint();
});
}
private static final class Label extends JLabel implements UIResource {
private Label(final String title) {
super(title);
setBorder(new EmptyBorder(5, 5,5,5));
}
}
}

10
src/test/java/UIDemo.java

@ -58,6 +58,11 @@ public final class UIDemo {
putClientProperty("JButton.variant", "shadow");
}});
}});
add(new JToggleButton("toggle"){{
putClientProperty("ToggleButton.variant", "slider");
setEnabled(false);
setSelected(true);
}});
}});
panel.add(new JPanel() {{
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
@ -113,13 +118,14 @@ public final class UIDemo {
panel.add(new JPanel() {{
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
add(new JButton("enabled") {{
setRolloverEnabled(true);
}});
add(new JButton("disabled") {{
setEnabled(false);
}});
add(defaultButton);
add(new JToggleButton("toggle"));
add(new JToggleButton("toggle"){{
putClientProperty("ToggleButton.variant", "slider");
}});
add(new JButton("square") {{
putClientProperty("JButton.buttonType", "square");
}});

Loading…
Cancel
Save