Browse Source

Added full demo of ButtonUI.

Fixed text staying bold when the button is no longer a default button.
Fixed text being approximately the same as the background while it is a default button and is a shadow variant.
Fixed button not updating when properties change.
Changed the thin property to be boolean based.

Signed-off-by: weisj <weisj@arcor.de>
pull/27/head
weisj 5 years ago
parent
commit
9d20af4dbd
  1. 68
      src/main/java/com/github/weisj/darklaf/ui/button/DarkButtonUI.java
  2. 2
      src/main/java/com/github/weisj/darklaf/ui/tabbedpane/MoreTabsButton.java
  3. 2
      src/main/java/com/github/weisj/darklaf/ui/tabbedpane/NewTabButton.java
  4. 2
      src/main/java/com/github/weisj/darklaf/ui/tabframe/DarkPanelPopupUI.java
  5. 2
      src/main/java/com/github/weisj/darklaf/ui/tabframe/DarkTabbedPopupUI.java
  6. 6
      src/test/java/UIDemo.java
  7. 106
      src/test/java/demo/ButtonDemo.java
  8. 31
      src/test/java/demo/ComponentDemo.java
  9. 56
      src/test/java/demo/DemoPanel.java
  10. 59
      src/test/java/demo/QuickColorChooser.java
  11. 69
      src/test/java/demo/SolidColorIcon.java

68
src/main/java/com/github/weisj/darklaf/ui/button/DarkButtonUI.java

@ -40,12 +40,14 @@ import javax.swing.plaf.basic.BasicHTML;
import javax.swing.text.View; import javax.swing.text.View;
import java.awt.*; import java.awt.*;
import java.awt.geom.RoundRectangle2D; import java.awt.geom.RoundRectangle2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
/** /**
* @author Konstantin Bulenkov * @author Konstantin Bulenkov
* @author Jannis Weis * @author Jannis Weis
*/ */
public class DarkButtonUI extends BasicButtonUI { public class DarkButtonUI extends BasicButtonUI implements PropertyChangeListener {
protected static final Rectangle viewRect = new Rectangle(); protected static final Rectangle viewRect = new Rectangle();
protected static final Rectangle textRect = new Rectangle(); protected static final Rectangle textRect = new Rectangle();
@ -100,18 +102,21 @@ public class DarkButtonUI extends BasicButtonUI {
squareArc = UIManager.getInt("Button.squareArc"); squareArc = UIManager.getInt("Button.squareArc");
} }
@Override @Contract("null -> false")
public void paint(final Graphics g, final JComponent c) { public static boolean isSquare(final Component c) {
GraphicsContext config = new GraphicsContext(g); return c instanceof JButton && Boolean.TRUE.equals(((JButton) c).getClientProperty("JButton.square"));
AbstractButton b = (AbstractButton) c; }
paintButton(g, c);
String text = layout(b, c, SwingUtilities2.getFontMetrics(b, g), @Override
b.getWidth(), b.getHeight()); protected void installListeners(final AbstractButton b) {
super.installListeners(b);
b.addPropertyChangeListener(this);
}
paintIcon(g, b, c); @Override
paintText(g, b, c, text); protected void uninstallListeners(final AbstractButton b) {
config.restore(); super.uninstallListeners(b);
b.removePropertyChangeListener(this);
} }
@Override @Override
@ -136,12 +141,18 @@ public class DarkButtonUI extends BasicButtonUI {
config.restore(); config.restore();
} }
protected Color getForeground(@NotNull final AbstractButton button) { @Override
Color fg = button.getForeground(); public void paint(final Graphics g, final JComponent c) {
if (fg instanceof UIResource && isDefaultButton(button)) { GraphicsContext config = new GraphicsContext(g);
fg = defaultForeground; AbstractButton b = (AbstractButton) c;
} paintButton(g, c);
return fg;
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 boolean isDefaultButton(final JComponent c) { protected boolean isDefaultButton(final JComponent c) {
@ -284,9 +295,12 @@ public class DarkButtonUI extends BasicButtonUI {
context.restore(); context.restore();
} }
@Contract("null -> false") protected Color getForeground(@NotNull final AbstractButton button) {
public static boolean isSquare(final Component c) { Color fg = button.getForeground();
return c instanceof JButton && "square".equals(((JButton) c).getClientProperty("JButton.buttonType")); if (fg instanceof UIResource && isDefaultButton(button) && !isShadowVariant(button)) {
fg = defaultForeground;
}
return fg;
} }
@Contract("null -> false") @Contract("null -> false")
@ -310,8 +324,11 @@ public class DarkButtonUI extends BasicButtonUI {
@Override @Override
public void update(final Graphics g, final JComponent c) { public void update(final Graphics g, final JComponent c) {
super.update(g, c); super.update(g, c);
if (c instanceof JButton && ((JButton) c).isDefaultButton() && !SystemInfo.isMac && !c.getFont().isBold()) { boolean isDefaultButton = isDefaultButton(c) && !SystemInfo.isMac;
if (isDefaultButton && !c.getFont().isBold()) {
c.setFont(c.getFont().deriveFont(Font.BOLD)); c.setFont(c.getFont().deriveFont(Font.BOLD));
} else if (!isDefaultButton && c.getFont().isBold()) {
c.setFont(c.getFont().deriveFont(Font.PLAIN));
} }
} }
@ -326,4 +343,13 @@ public class DarkButtonUI extends BasicButtonUI {
return new RoundRectangle2D.Float(bs, bs, c.getWidth() - 2 * bs, c.getWidth() - 2 * bs, return new RoundRectangle2D.Float(bs, bs, c.getWidth() - 2 * bs, c.getWidth() - 2 * bs,
arc, arc).contains(x, y); arc, arc).contains(x, y);
} }
@Override
public void propertyChange(@NotNull final PropertyChangeEvent evt) {
String key = evt.getPropertyName();
if (key.startsWith("JButton.")) {
button.repaint();
button.revalidate();
}
}
} }

2
src/main/java/com/github/weisj/darklaf/ui/tabbedpane/MoreTabsButton.java

@ -44,7 +44,7 @@ public class MoreTabsButton extends DarkTabAreaButton {
icon = ui.getMoreTabsIcon(); icon = ui.getMoreTabsIcon();
setIcon(EmptyIcon.create(icon.getIconWidth(), icon.getIconHeight())); setIcon(EmptyIcon.create(icon.getIconWidth(), icon.getIconHeight()));
putClientProperty("JButton.variant", "onlyLabel"); putClientProperty("JButton.variant", "onlyLabel");
putClientProperty("JButton.buttonType", "square"); putClientProperty("JButton.square", true);
setFont(getFont().deriveFont(8f)); setFont(getFont().deriveFont(8f));
} }

2
src/main/java/com/github/weisj/darklaf/ui/tabbedpane/NewTabButton.java

@ -52,7 +52,7 @@ public class NewTabButton extends JPanel implements UIResource {
JButton button = new JButton(); JButton button = new JButton();
button.setIcon(ui.getNewTabIcon()); button.setIcon(ui.getNewTabIcon());
button.putClientProperty("JButton.variant", "shadow"); button.putClientProperty("JButton.variant", "shadow");
button.putClientProperty("JButton.buttonType", "square"); button.putClientProperty("JButton.square", true);
button.putClientProperty("JButton.alternativeArc", Boolean.TRUE); button.putClientProperty("JButton.alternativeArc", Boolean.TRUE);
button.putClientProperty("JButton.thin", Boolean.TRUE); button.putClientProperty("JButton.thin", Boolean.TRUE);
button.setRolloverEnabled(true); button.setRolloverEnabled(true);

2
src/main/java/com/github/weisj/darklaf/ui/tabframe/DarkPanelPopupUI.java

@ -374,7 +374,7 @@ public class DarkPanelPopupUI extends DarkPanelUI implements PropertyChangeListe
public HeaderButton(@NotNull final Icon icon, final DarkPanelPopupUI ui) { public HeaderButton(@NotNull final Icon icon, final DarkPanelPopupUI ui) {
super(icon); super(icon);
this.ui = ui; this.ui = ui;
putClientProperty("JButton.buttonType", "square"); putClientProperty("JButton.square", true);
putClientProperty("JButton.alternativeArc", Boolean.TRUE); putClientProperty("JButton.alternativeArc", Boolean.TRUE);
putClientProperty("JButton.variant", "shadow"); putClientProperty("JButton.variant", "shadow");
setRolloverEnabled(true); setRolloverEnabled(true);

2
src/main/java/com/github/weisj/darklaf/ui/tabframe/DarkTabbedPopupUI.java

@ -158,7 +158,7 @@ public class DarkTabbedPopupUI extends DarkPanelPopupUI {
protected JButton createButton() { protected JButton createButton() {
HeaderButton button = new HeaderButton(ui.getNewTabIcon(), DarkTabbedPopupUI.this); HeaderButton button = new HeaderButton(ui.getNewTabIcon(), DarkTabbedPopupUI.this);
button.putClientProperty("JButton.variant", "shadow"); button.putClientProperty("JButton.variant", "shadow");
button.putClientProperty("JButton.buttonType", "square"); button.putClientProperty("JButton.square", true);
button.putClientProperty("JButton.thin", Boolean.TRUE); button.putClientProperty("JButton.thin", Boolean.TRUE);
button.setRolloverEnabled(true); button.setRolloverEnabled(true);
button.setOpaque(false); button.setOpaque(false);

6
src/test/java/UIDemo.java

@ -87,12 +87,12 @@ public final class UIDemo {
}}); }});
add(new JButton(folderIcon) {{ add(new JButton(folderIcon) {{
setRolloverEnabled(true); setRolloverEnabled(true);
putClientProperty("JButton.buttonType", "square"); putClientProperty("JButton.square", true);
putClientProperty("JButton.variant", "shadow"); putClientProperty("JButton.variant", "shadow");
}}); }});
add(new JButton(folderIcon) {{ add(new JButton(folderIcon) {{
setRolloverEnabled(true); setRolloverEnabled(true);
putClientProperty("JButton.buttonType", "square"); putClientProperty("JButton.square", true);
putClientProperty("JButton.thin", Boolean.TRUE); putClientProperty("JButton.thin", Boolean.TRUE);
putClientProperty("JButton.alternativeArc", Boolean.TRUE); putClientProperty("JButton.alternativeArc", Boolean.TRUE);
putClientProperty("JButton.variant", "shadow"); putClientProperty("JButton.variant", "shadow");
@ -166,7 +166,7 @@ public final class UIDemo {
putClientProperty("ToggleButton.variant", "slider"); putClientProperty("ToggleButton.variant", "slider");
}}); }});
add(new JButton("square") {{ add(new JButton("square") {{
putClientProperty("JButton.buttonType", "square"); putClientProperty("JButton.square", true);
}}); }});
}}); }});
panel.add(taskpanecontainer); panel.add(taskpanecontainer);

106
src/test/java/demo/ButtonDemo.java

@ -0,0 +1,106 @@
/*
* MIT License
*
* Copyright (c) 2020 Jannis Weis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package demo;
import com.github.weisj.darklaf.LafManager;
import com.github.weisj.darklaf.icons.IconLoader;
import javax.swing.*;
import java.awt.*;
public class ButtonDemo implements ComponentDemo {
public static void main(final String[] args) {
SwingUtilities.invokeLater(() -> {
LafManager.install();
JFrame frame = DemoPanel.createFrame();
frame.setContentPane(new ButtonDemo().createComponent());
frame.pack();
frame.setVisible(true);
});
}
@Override
public JComponent createComponent() {
Icon icon = IconLoader.get().getIcon("files/folder.svg", 19, 19, true);
JButton button = new JButton("Test Button", icon);
DemoPanel panel = new DemoPanel(button);
JPanel controlPanel = panel.getControls();
controlPanel.setLayout(new GridLayout(5, 2));
controlPanel.add(new JCheckBox("enabled") {{
setSelected(button.isEnabled());
addActionListener(e -> button.setEnabled(isSelected()));
}});
controlPanel.add(new JCheckBox("default") {{
setSelected(button.isDefaultButton());
addActionListener(e -> SwingUtilities.getRootPane(button).setDefaultButton(isSelected() ? button
: null));
}});
controlPanel.add(new JCheckBox("LeftToRight") {{
setSelected(button.getComponentOrientation().isLeftToRight());
addActionListener(e -> button.setComponentOrientation(isSelected() ? ComponentOrientation.LEFT_TO_RIGHT
: ComponentOrientation.RIGHT_TO_LEFT));
}});
controlPanel.add(new JCheckBox("Rollover") {{
setSelected(button.isRolloverEnabled());
addActionListener(e -> button.setRolloverEnabled(isSelected()));
}});
controlPanel.add(new JCheckBox("JButton.square") {{
setSelected(false);
addActionListener(e -> button.putClientProperty("JButton.square", isSelected()));
}});
controlPanel.add(new JCheckBox("JButton.thin") {{
setSelected(false);
addActionListener(e -> button.putClientProperty("JButton.thin", isSelected()));
}});
controlPanel.add(new JCheckBox("JButton.alternativeArc") {{
setSelected(false);
addActionListener(e -> button.putClientProperty("JButton.alternativeArc", isSelected()));
}});
controlPanel.add(new JComboBox<String>() {{
addItem("JButton.variant = onlyLabel");
addItem("JButton.variant = shadow");
addItem("JButton.variant = fullShadow");
addItem("no JButton.variant");
setSelectedItem("no JButton.variant");
addItemListener(e -> {
if (e.getItem().equals("JButton.variant = onlyLabel")) {
button.putClientProperty("JButton.variant", "onlyLabel");
} else if (e.getItem().equals("JButton.variant = shadow")) {
button.putClientProperty("JButton.variant", "shadow");
} else if (e.getItem().equals("JButton.variant = fullShadow")) {
button.putClientProperty("JButton.variant", "fullShadow");
} else {
button.putClientProperty("JButton.variant", null);
}
});
}});
controlPanel.add(new QuickColorChooser("JButton.shadow.hover", Color.BLACK,
(b, c) -> button.putClientProperty("JButton.shadow.hover", b ? c : null)));
controlPanel.add(new QuickColorChooser("JButton.shadow.click", Color.BLACK,
(b, c) -> button.putClientProperty("JButton.shadow.click", b ? c : null)));
return panel;
}
}

31
src/test/java/demo/ComponentDemo.java

@ -0,0 +1,31 @@
/*
* MIT License
*
* Copyright (c) 2020 Jannis Weis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package demo;
import javax.swing.*;
public interface ComponentDemo {
JComponent createComponent();
}

56
src/test/java/demo/DemoPanel.java

@ -0,0 +1,56 @@
/*
* MIT License
*
* Copyright (c) 2020 Jannis Weis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package demo;
import com.github.weisj.darklaf.components.border.DarkBorders;
import javax.swing.*;
import java.awt.*;
public class DemoPanel extends JPanel {
private final JPanel controls;
public DemoPanel(final JComponent component) {
super(new BorderLayout());
JPanel content = new JPanel(new GridBagLayout());
content.add(component, null);
add(content, BorderLayout.CENTER);
controls = new JPanel();
controls.setBorder(DarkBorders.createLineBorder(1, 0, 0, 0));
controls.setLayout(new BoxLayout(controls, BoxLayout.X_AXIS));
add(controls, BorderLayout.SOUTH);
}
public static JFrame createFrame() {
JFrame frame = new JFrame();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
return frame;
}
public JPanel getControls() {
return controls;
}
}

59
src/test/java/demo/QuickColorChooser.java

@ -0,0 +1,59 @@
/*
* MIT License
*
* Copyright (c) 2020 Jannis Weis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package demo;
import com.github.weisj.darklaf.decorators.MouseClickListener;
import javax.swing.*;
import java.awt.*;
import java.util.function.BiConsumer;
public class QuickColorChooser extends JPanel {
private final SolidColorIcon icon;
private final JCheckBox checkBox;
public QuickColorChooser(final String title, final Color color, final BiConsumer<Boolean, Color> onStatusChange) {
super(new FlowLayout(FlowLayout.LEFT, 0, 0));
icon = new SolidColorIcon(color);
JLabel label = new JLabel(title, icon, JLabel.LEFT);
checkBox = new JCheckBox();
checkBox.addActionListener(e -> onStatusChange.accept(isSelected(), getColor()));
label.addMouseListener((MouseClickListener) e -> {
Color c = JColorChooser.showDialog(QuickColorChooser.this, title, icon.getColor());
onStatusChange.accept(isSelected(), c);
icon.setColor(c);
});
add(checkBox);
add(label);
}
public boolean isSelected() {
return checkBox.isSelected();
}
public Color getColor() {
return icon.getColor();
}
}

69
src/test/java/demo/SolidColorIcon.java

@ -0,0 +1,69 @@
/*
* MIT License
*
* Copyright (c) 2020 Jannis Weis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package demo;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
final class SolidColorIcon implements Icon {
private final int width;
private final int height;
private Color color;
SolidColorIcon(final Color color) {
this(color, 16, 16);
}
private SolidColorIcon(final Color color, final int width, final int height) {
this.color = color;
this.width = width;
this.height = height;
}
@Override
public void paintIcon(final Component c, @NotNull final Graphics g, final int x, final int y) {
g.setColor(color);
g.fillRect(x, y, getIconWidth(), getIconHeight());
}
@Override
public int getIconWidth() {
return width;
}
@Override
public int getIconHeight() {
return height;
}
public Color getColor() {
return color;
}
public void setColor(final Color c) {
this.color = c;
}
}
Loading…
Cancel
Save