Browse Source

Reduce amount of layout operations for buttons.

pull/214/head
weisj 4 years ago
parent
commit
4a74244a29
  1. 6
      core/src/main/java/com/github/weisj/darklaf/graphics/StringPainter.java
  2. 209
      core/src/main/java/com/github/weisj/darklaf/ui/button/DarkButtonUI.java
  3. 4
      core/src/main/java/com/github/weisj/darklaf/ui/togglebutton/DarkToggleButtonUI.java

6
core/src/main/java/com/github/weisj/darklaf/graphics/StringPainter.java

@ -159,11 +159,11 @@ public class StringPainter {
if (v != null) {
v.paint(drawingGraphics, textRect);
} else {
textRect.y += asc;
int textY = textRect.y + asc;
if (mnemIndex >= 0) {
SwingUtilities2.drawStringUnderlineCharAt(c, drawingGraphics, text, mnemIndex, textRect.x, textRect.y);
SwingUtilities2.drawStringUnderlineCharAt(c, drawingGraphics, text, mnemIndex, textRect.x, textY);
} else {
SwingUtilities2.drawString(c, drawingGraphics, text, textRect.x, textRect.y);
SwingUtilities2.drawString(c, drawingGraphics, text, textRect.x, textY);
}
}

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

@ -33,8 +33,6 @@ import javax.swing.plaf.basic.BasicButtonListener;
import javax.swing.plaf.basic.BasicButtonUI;
import javax.swing.plaf.basic.BasicGraphicsUtils;
import sun.swing.SwingUtilities2;
import com.github.weisj.darklaf.components.tooltip.ToolTipStyle;
import com.github.weisj.darklaf.delegate.AbstractButtonLayoutDelegate;
import com.github.weisj.darklaf.graphics.GraphicsContext;
@ -51,11 +49,16 @@ import com.github.weisj.darklaf.util.PropertyUtil;
/** @author Jannis Weis */
public class DarkButtonUI extends BasicButtonUI implements ButtonConstants {
protected static final Rectangle viewRect = new Rectangle();
protected static final Rectangle textRect = new Rectangle();
protected static final Rectangle iconRect = new Rectangle();
protected static final RoundRectangle2D hitArea = new RoundRectangle2D.Float();
protected static final AbstractButtonLayoutDelegate layoutDelegate = new ButtonLayoutDelegate();
protected boolean isDefaultButton = false;
protected final Rectangle viewRect = new Rectangle();
protected final Rectangle textRect = new Rectangle();
protected final Rectangle iconRect = new Rectangle();
protected String displayText;
protected int borderSize;
protected int shadowHeight;
protected boolean drawOutline;
@ -98,6 +101,7 @@ public class DarkButtonUI extends BasicButtonUI implements ButtonConstants {
@Override
protected void installDefaults(final AbstractButton b) {
super.installDefaults(b);
b.setLayout(createLayout());
PropertyUtil.installProperty(b, ToolTipConstants.KEY_STYLE,
ToolTipStyle.parse(UIManager.get("Button.toolTipStyle")));
LookAndFeel.installProperty(b, PropertyKey.OPAQUE, false);
@ -133,6 +137,10 @@ public class DarkButtonUI extends BasicButtonUI implements ButtonConstants {
updateMargins(b);
}
protected LayoutManager createLayout() {
return new DarkButtonLayout();
}
@Override
protected void installListeners(final AbstractButton b) {
super.installListeners(b);
@ -145,6 +153,12 @@ public class DarkButtonUI extends BasicButtonUI implements ButtonConstants {
return new DarkButtonListener(b, this);
}
@Override
protected void uninstallDefaults(final AbstractButton b) {
super.uninstallDefaults(b);
b.setLayout(null);
}
@Override
protected void uninstallListeners(final AbstractButton b) {
super.uninstallListeners(b);
@ -152,19 +166,26 @@ public class DarkButtonUI extends BasicButtonUI implements ButtonConstants {
keyboardActions = null;
}
protected void validateLayout() {
boolean defButton = ButtonConstants.isDefaultButton(button);
if (defButton != isDefaultButton) {
isDefaultButton = defButton;
button.doLayout();
}
}
@Override
public void paint(final Graphics g, final JComponent c) {
validateLayout();
GraphicsContext config = new GraphicsContext(g);
AbstractButton b = (AbstractButton) c;
prepareDelegate(b);
String text = layout(layoutDelegate, b, SwingUtilities2.getFontMetrics(b, g, layoutDelegate.getFont()),
b.getWidth(), b.getHeight());
paintButtonBackground(g, c);
paintIcon(g, b, c);
config.restoreClip();
paintText(g, b, text);
paintText(g, b, displayText);
}
protected void paintButtonBackground(final Graphics g, final JComponent c) {
@ -203,24 +224,34 @@ public class DarkButtonUI extends BasicButtonUI implements ButtonConstants {
AlignmentExt corner = DarkButtonBorder.getCornerFlag(c);
Rectangle bgRect = getEffectiveRect(width, height, -(effectiveArc + 1), corner);
paintDarklafBorderBgImpl(c, g, showShadow, shadow, effectiveArc, bgRect);
}
protected void paintDarklafBorderBgImpl(final AbstractButton c, final Graphics2D g, final boolean showShadow,
final int shadow, final int effectiveArc, final Rectangle bgRect) {
if (c.isEnabled() && showShadow && PaintUtil.getShadowComposite().getAlpha() != 0) {
g.setColor(shadowColor);
Composite comp = g.getComposite();
g.setComposite(PaintUtil.getShadowComposite());
int stroke = (int) PaintUtil.getStrokeWidth(g);
paintBackgroundRect(g, effectiveArc * 2, bgRect.x, bgRect.y + shadow + stroke, bgRect.width, bgRect.height);
g.setComposite(comp);
paintShadow(g, shadow, effectiveArc, bgRect);
}
g.setColor(getBackgroundColor(c));
paintBackgroundRect(g, effectiveArc, bgRect);
}
private void paintBackgroundRect(final Graphics2D g2, final int effectiveArc, final Rectangle bgRect) {
private void paintShadow(final Graphics2D g, final int shadow, final int effectiveArc, final Rectangle bgRect) {
g.setColor(shadowColor);
Composite comp = g.getComposite();
g.setComposite(PaintUtil.getShadowComposite());
int stroke = (int) PaintUtil.getStrokeWidth(g);
paintBackgroundRect(g, effectiveArc * 2, bgRect.x, bgRect.y + shadow + stroke, bgRect.width, bgRect.height);
g.setComposite(comp);
}
protected void paintBackgroundRect(final Graphics2D g2, final int effectiveArc, final Rectangle bgRect) {
paintBackgroundRect(g2, effectiveArc, bgRect.x, bgRect.y, bgRect.width, bgRect.height);
}
private void paintBackgroundRect(final Graphics2D g2, final int effectiveArc, final int x, final int y,
protected void paintBackgroundRect(final Graphics2D g2, final int effectiveArc, final int x, final int y,
final int width, final int height) {
if (effectiveArc == 0) {
g2.fillRect(x, y, width, height);
@ -267,29 +298,35 @@ public class DarkButtonUI extends BasicButtonUI implements ButtonConstants {
int h = height - y - Math.max(ins.bottom, margin.bottom);
GraphicsUtil.setupAAPainting(g);
g.setColor(getBorderlessBackground(b));
if (ButtonConstants.isBorderlessRectangular(b)) {
g.fillRect(x, y, w, h);
paintBorderlessRectangularBackgroundIml(b, g, x, y, w, h);
} else if (ButtonConstants.doConvertToBorderless(b)) {
int size = Math.min(w, h);
if (!drawOutline) {
g.fillRoundRect((width - size) / 2, (height - size) / 2, size, size, arc, arc);
} else {
g.setColor(getBorderlessOutline(b));
PaintUtil.paintLineBorder(g, (width - size) / 2.0f, (height - size) / 2.0f, size, size, arc);
}
paintBorderlessBackgroundImpl(b, g, arc, (width - size) / 2, (height - size) / 2, size, size);
} else {
if (!drawOutline) {
g.fillRoundRect(x, y, w, h, arc, arc);
} else {
g.setColor(getBorderlessOutline(b));
PaintUtil.paintLineBorder(g, x, y, w, h, arc);
}
paintBorderlessBackgroundImpl(b, g, arc, x, y, w, h);
}
}
}
protected boolean isRolloverBorderless(final AbstractButton b) {
protected void paintBorderlessRectangularBackgroundIml(final AbstractButton b, final Graphics2D g, final int x,
final int y, final int w, final int h) {
g.setColor(getBorderlessBackground(b));
g.fillRect(x, y, w, h);
}
protected void paintBorderlessBackgroundImpl(final AbstractButton b, final Graphics2D g, final int arc, final int x,
final int y, final int w, final int h) {
if (!drawOutline) {
g.setColor(getBorderlessBackground(b));
g.fillRoundRect(x, y, w, h, arc, arc);
} else {
g.setColor(getBorderlessOutline(b));
PaintUtil.paintLineBorder(g, x, y, w, h, arc);
}
}
public boolean isRolloverBorderless(final AbstractButton b) {
return b.isEnabled() && b.getModel().isRollover();
}
@ -331,8 +368,7 @@ public class DarkButtonUI extends BasicButtonUI implements ButtonConstants {
protected Color getForeground(final AbstractButton button) {
Color fg = button.getForeground();
if (fg instanceof UIResource && ButtonConstants.isDefaultButton(button)
&& !ButtonConstants.isBorderlessVariant(button)) {
if (fg instanceof UIResource && isDefaultButton && !ButtonConstants.isBorderlessVariant(button)) {
fg = defaultForeground;
}
if (fg instanceof UIResource && !button.getModel().isEnabled()) {
@ -342,10 +378,16 @@ public class DarkButtonUI extends BasicButtonUI implements ButtonConstants {
}
protected Color getBackgroundColor(final AbstractButton b) {
boolean defaultButton = ButtonConstants.isDefaultButton(b);
boolean defaultButton = isDefaultButton;
boolean rollOver = b.isRolloverEnabled() && b.getModel().isRollover();
boolean clicked = b.getModel().isArmed();
if (b.isEnabled()) {
boolean enabled = b.isEnabled();
return getBackgroundColor(b, defaultButton, rollOver, clicked, enabled);
}
protected Color getBackgroundColor(final AbstractButton b, final boolean defaultButton, final boolean rollOver,
final boolean clicked, final boolean enabled) {
if (enabled) {
if (defaultButton) {
if (clicked) {
return defaultClickBackground;
@ -373,38 +415,16 @@ public class DarkButtonUI extends BasicButtonUI implements ButtonConstants {
: PropertyUtil.getColor(c, KEY_HOVER_COLOR, borderlessHover);
}
protected boolean isArmedBorderless(final AbstractButton b) {
public boolean isArmedBorderless(final AbstractButton b) {
return b.getModel().isArmed();
}
protected Color getBorderlessOutline(final AbstractButton c) {
boolean armed = c.getModel().isArmed();
return armed ? borderlessOutlineClick : borderlessOutlineHover;
public Color getBorderlessOutline(final AbstractButton c) {
return getBorderlessOutline(isArmedBorderless(c));
}
protected String layout(final AbstractButtonLayoutDelegate bl, final AbstractButton b, final FontMetrics fm,
final int width, final int height) {
Insets i = DarkUIUtil.addInsets(b.getInsets(), b.getMargin());
AlignmentExt corner = DarkButtonBorder.getCornerFlag(b);
if (corner != null) {
Insets insetMask = new Insets(borderSize, borderSize, borderSize, borderSize);
insetMask = corner.maskInsetsInverted(insetMask, 0);
i.left -= insetMask.left;
i.right -= insetMask.right;
i.top -= insetMask.top;
i.bottom -= insetMask.bottom;
}
viewRect.setRect(0, 0, width, height);
DarkUIUtil.applyInsets(viewRect, i);
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(bl, fm, bl.getText(), bl.getIcon(), bl.getVerticalAlignment(),
bl.getHorizontalAlignment(), bl.getVerticalTextPosition(), bl.getHorizontalTextPosition(), viewRect,
iconRect, textRect, bl.getText() == null || ButtonConstants.isIconOnly(b) ? 0 : bl.getIconTextGap());
public Color getBorderlessOutline(final boolean armed) {
return armed ? borderlessOutlineClick : borderlessOutlineHover;
}
@Override
@ -455,6 +475,10 @@ public class DarkButtonUI extends BasicButtonUI implements ButtonConstants {
return hitArea.contains(x, y);
}
public boolean getDrawOutline(final Component c) {
return drawOutline && ButtonConstants.isBorderless(c);
}
protected static class ButtonLayoutDelegate extends AbstractButtonLayoutDelegate {
protected Font font;
@ -468,4 +492,63 @@ public class DarkButtonUI extends BasicButtonUI implements ButtonConstants {
return font;
}
}
public class DarkButtonLayout implements LayoutManager {
@Override
public void addLayoutComponent(final String name, final Component comp) {}
@Override
public void removeLayoutComponent(final Component comp) {}
@Override
public Dimension preferredLayoutSize(final Container parent) {
// Still managed by BasicButtonUI#getPreferredSize
return null;
}
@Override
public Dimension minimumLayoutSize(final Container parent) {
// Still managed by BasicButtonUI#getMinimumSize
return null;
}
@Override
public void layoutContainer(final Container parent) {
AbstractButton b = (AbstractButton) parent;
prepareDelegate(b);
FontMetrics fm = b.getFontMetrics(layoutDelegate.getFont());
displayText = layout(layoutDelegate, b, fm, b.getWidth(), b.getHeight());
}
protected String layout(final AbstractButtonLayoutDelegate bl, final AbstractButton b, final FontMetrics fm,
final int width, final int height) {
prepareContentRects(b, width, height);
// layout the text and icon
return SwingUtilities.layoutCompoundLabel(bl, fm, bl.getText(), bl.getIcon(), bl.getVerticalAlignment(),
bl.getHorizontalAlignment(), bl.getVerticalTextPosition(), bl.getHorizontalTextPosition(), viewRect,
iconRect, textRect,
bl.getText() == null || ButtonConstants.isIconOnly(b) ? 0 : bl.getIconTextGap());
}
protected void prepareContentRects(final AbstractButton b, final int width, final int height) {
Insets i = DarkUIUtil.addInsets(b.getInsets(), b.getMargin());
AlignmentExt corner = DarkButtonBorder.getCornerFlag(b);
if (corner != null) {
Insets insetMask = new Insets(borderSize, borderSize, borderSize, borderSize);
insetMask = corner.maskInsetsInverted(insetMask, 0);
i.left -= insetMask.left;
i.right -= insetMask.right;
i.top -= insetMask.top;
i.bottom -= insetMask.bottom;
}
viewRect.setRect(0, 0, width, height);
DarkUIUtil.applyInsets(viewRect, i);
textRect.x = textRect.y = textRect.width = textRect.height = 0;
iconRect.x = iconRect.y = iconRect.width = iconRect.height = 0;
}
}
}

4
core/src/main/java/com/github/weisj/darklaf/ui/togglebutton/DarkToggleButtonUI.java

@ -157,12 +157,12 @@ public class DarkToggleButtonUI extends DarkButtonUI implements ToggleButtonCons
}
@Override
protected boolean isRolloverBorderless(final AbstractButton b) {
public boolean isRolloverBorderless(final AbstractButton b) {
return super.isRolloverBorderless(b) || b.isSelected();
}
@Override
protected boolean isArmedBorderless(final AbstractButton b) {
public boolean isArmedBorderless(final AbstractButton b) {
return super.isArmedBorderless(b) || b.isSelected();
}

Loading…
Cancel
Save