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) { if (v != null) {
v.paint(drawingGraphics, textRect); v.paint(drawingGraphics, textRect);
} else { } else {
textRect.y += asc; int textY = textRect.y + asc;
if (mnemIndex >= 0) { if (mnemIndex >= 0) {
SwingUtilities2.drawStringUnderlineCharAt(c, drawingGraphics, text, mnemIndex, textRect.x, textRect.y); SwingUtilities2.drawStringUnderlineCharAt(c, drawingGraphics, text, mnemIndex, textRect.x, textY);
} else { } 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.BasicButtonUI;
import javax.swing.plaf.basic.BasicGraphicsUtils; import javax.swing.plaf.basic.BasicGraphicsUtils;
import sun.swing.SwingUtilities2;
import com.github.weisj.darklaf.components.tooltip.ToolTipStyle; import com.github.weisj.darklaf.components.tooltip.ToolTipStyle;
import com.github.weisj.darklaf.delegate.AbstractButtonLayoutDelegate; import com.github.weisj.darklaf.delegate.AbstractButtonLayoutDelegate;
import com.github.weisj.darklaf.graphics.GraphicsContext; import com.github.weisj.darklaf.graphics.GraphicsContext;
@ -51,11 +49,16 @@ import com.github.weisj.darklaf.util.PropertyUtil;
/** @author Jannis Weis */ /** @author Jannis Weis */
public class DarkButtonUI extends BasicButtonUI implements ButtonConstants { 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 RoundRectangle2D hitArea = new RoundRectangle2D.Float();
protected static final AbstractButtonLayoutDelegate layoutDelegate = new ButtonLayoutDelegate(); 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 borderSize;
protected int shadowHeight; protected int shadowHeight;
protected boolean drawOutline; protected boolean drawOutline;
@ -98,6 +101,7 @@ public class DarkButtonUI extends BasicButtonUI implements ButtonConstants {
@Override @Override
protected void installDefaults(final AbstractButton b) { protected void installDefaults(final AbstractButton b) {
super.installDefaults(b); super.installDefaults(b);
b.setLayout(createLayout());
PropertyUtil.installProperty(b, ToolTipConstants.KEY_STYLE, PropertyUtil.installProperty(b, ToolTipConstants.KEY_STYLE,
ToolTipStyle.parse(UIManager.get("Button.toolTipStyle"))); ToolTipStyle.parse(UIManager.get("Button.toolTipStyle")));
LookAndFeel.installProperty(b, PropertyKey.OPAQUE, false); LookAndFeel.installProperty(b, PropertyKey.OPAQUE, false);
@ -133,6 +137,10 @@ public class DarkButtonUI extends BasicButtonUI implements ButtonConstants {
updateMargins(b); updateMargins(b);
} }
protected LayoutManager createLayout() {
return new DarkButtonLayout();
}
@Override @Override
protected void installListeners(final AbstractButton b) { protected void installListeners(final AbstractButton b) {
super.installListeners(b); super.installListeners(b);
@ -145,6 +153,12 @@ public class DarkButtonUI extends BasicButtonUI implements ButtonConstants {
return new DarkButtonListener(b, this); return new DarkButtonListener(b, this);
} }
@Override
protected void uninstallDefaults(final AbstractButton b) {
super.uninstallDefaults(b);
b.setLayout(null);
}
@Override @Override
protected void uninstallListeners(final AbstractButton b) { protected void uninstallListeners(final AbstractButton b) {
super.uninstallListeners(b); super.uninstallListeners(b);
@ -152,19 +166,26 @@ public class DarkButtonUI extends BasicButtonUI implements ButtonConstants {
keyboardActions = null; keyboardActions = null;
} }
protected void validateLayout() {
boolean defButton = ButtonConstants.isDefaultButton(button);
if (defButton != isDefaultButton) {
isDefaultButton = defButton;
button.doLayout();
}
}
@Override @Override
public void paint(final Graphics g, final JComponent c) { public void paint(final Graphics g, final JComponent c) {
validateLayout();
GraphicsContext config = new GraphicsContext(g); GraphicsContext config = new GraphicsContext(g);
AbstractButton b = (AbstractButton) c; AbstractButton b = (AbstractButton) c;
prepareDelegate(b);
String text = layout(layoutDelegate, b, SwingUtilities2.getFontMetrics(b, g, layoutDelegate.getFont()),
b.getWidth(), b.getHeight());
paintButtonBackground(g, c); paintButtonBackground(g, c);
paintIcon(g, b, c); paintIcon(g, b, c);
config.restoreClip(); config.restoreClip();
paintText(g, b, text); paintText(g, b, displayText);
} }
protected void paintButtonBackground(final Graphics g, final JComponent c) { 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); AlignmentExt corner = DarkButtonBorder.getCornerFlag(c);
Rectangle bgRect = getEffectiveRect(width, height, -(effectiveArc + 1), corner); 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) { if (c.isEnabled() && showShadow && PaintUtil.getShadowComposite().getAlpha() != 0) {
g.setColor(shadowColor); paintShadow(g, shadow, effectiveArc, bgRect);
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);
} }
g.setColor(getBackgroundColor(c)); g.setColor(getBackgroundColor(c));
paintBackgroundRect(g, effectiveArc, bgRect); 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); 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) { final int width, final int height) {
if (effectiveArc == 0) { if (effectiveArc == 0) {
g2.fillRect(x, y, width, height); 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); int h = height - y - Math.max(ins.bottom, margin.bottom);
GraphicsUtil.setupAAPainting(g); GraphicsUtil.setupAAPainting(g);
g.setColor(getBorderlessBackground(b));
if (ButtonConstants.isBorderlessRectangular(b)) { if (ButtonConstants.isBorderlessRectangular(b)) {
g.fillRect(x, y, w, h); paintBorderlessRectangularBackgroundIml(b, g, x, y, w, h);
} else if (ButtonConstants.doConvertToBorderless(b)) { } else if (ButtonConstants.doConvertToBorderless(b)) {
int size = Math.min(w, h); int size = Math.min(w, h);
if (!drawOutline) { paintBorderlessBackgroundImpl(b, g, arc, (width - size) / 2, (height - size) / 2, size, size);
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);
}
} else { } else {
if (!drawOutline) { paintBorderlessBackgroundImpl(b, g, arc, x, y, w, h);
g.fillRoundRect(x, y, w, h, arc, arc);
} else {
g.setColor(getBorderlessOutline(b));
PaintUtil.paintLineBorder(g, x, y, w, h, arc);
}
} }
} }
} }
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(); return b.isEnabled() && b.getModel().isRollover();
} }
@ -331,8 +368,7 @@ public class DarkButtonUI extends BasicButtonUI implements ButtonConstants {
protected Color getForeground(final AbstractButton button) { protected Color getForeground(final AbstractButton button) {
Color fg = button.getForeground(); Color fg = button.getForeground();
if (fg instanceof UIResource && ButtonConstants.isDefaultButton(button) if (fg instanceof UIResource && isDefaultButton && !ButtonConstants.isBorderlessVariant(button)) {
&& !ButtonConstants.isBorderlessVariant(button)) {
fg = defaultForeground; fg = defaultForeground;
} }
if (fg instanceof UIResource && !button.getModel().isEnabled()) { if (fg instanceof UIResource && !button.getModel().isEnabled()) {
@ -342,10 +378,16 @@ public class DarkButtonUI extends BasicButtonUI implements ButtonConstants {
} }
protected Color getBackgroundColor(final AbstractButton b) { protected Color getBackgroundColor(final AbstractButton b) {
boolean defaultButton = ButtonConstants.isDefaultButton(b); boolean defaultButton = isDefaultButton;
boolean rollOver = b.isRolloverEnabled() && b.getModel().isRollover(); boolean rollOver = b.isRolloverEnabled() && b.getModel().isRollover();
boolean clicked = b.getModel().isArmed(); 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 (defaultButton) {
if (clicked) { if (clicked) {
return defaultClickBackground; return defaultClickBackground;
@ -373,38 +415,16 @@ public class DarkButtonUI extends BasicButtonUI implements ButtonConstants {
: PropertyUtil.getColor(c, KEY_HOVER_COLOR, borderlessHover); : PropertyUtil.getColor(c, KEY_HOVER_COLOR, borderlessHover);
} }
protected boolean isArmedBorderless(final AbstractButton b) { public boolean isArmedBorderless(final AbstractButton b) {
return b.getModel().isArmed(); return b.getModel().isArmed();
} }
protected Color getBorderlessOutline(final AbstractButton c) { public Color getBorderlessOutline(final AbstractButton c) {
boolean armed = c.getModel().isArmed(); return getBorderlessOutline(isArmedBorderless(c));
return armed ? borderlessOutlineClick : borderlessOutlineHover;
} }
protected String layout(final AbstractButtonLayoutDelegate bl, final AbstractButton b, final FontMetrics fm, public Color getBorderlessOutline(final boolean armed) {
final int width, final int height) { return armed ? borderlessOutlineClick : borderlessOutlineHover;
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());
} }
@Override @Override
@ -455,6 +475,10 @@ public class DarkButtonUI extends BasicButtonUI implements ButtonConstants {
return hitArea.contains(x, y); return hitArea.contains(x, y);
} }
public boolean getDrawOutline(final Component c) {
return drawOutline && ButtonConstants.isBorderless(c);
}
protected static class ButtonLayoutDelegate extends AbstractButtonLayoutDelegate { protected static class ButtonLayoutDelegate extends AbstractButtonLayoutDelegate {
protected Font font; protected Font font;
@ -468,4 +492,63 @@ public class DarkButtonUI extends BasicButtonUI implements ButtonConstants {
return font; 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 @Override
protected boolean isRolloverBorderless(final AbstractButton b) { public boolean isRolloverBorderless(final AbstractButton b) {
return super.isRolloverBorderless(b) || b.isSelected(); return super.isRolloverBorderless(b) || b.isSelected();
} }
@Override @Override
protected boolean isArmedBorderless(final AbstractButton b) { public boolean isArmedBorderless(final AbstractButton b) {
return super.isArmedBorderless(b) || b.isSelected(); return super.isArmedBorderless(b) || b.isSelected();
} }

Loading…
Cancel
Save