Browse Source

Added loading icons.

Added LoadingIndicator.
pull/170/head
weisj 5 years ago
parent
commit
1a46895b2c
  1. 69
      core/src/main/java/com/github/weisj/darklaf/components/RotatableIconAnimator.java
  2. 127
      core/src/main/java/com/github/weisj/darklaf/components/loading/LoadingIndicator.java
  3. 25
      core/src/main/java/com/github/weisj/darklaf/graphics/Animator.java
  4. 12
      core/src/main/resources/com/github/weisj/darklaf/icons/progress/pause.svg
  5. 9
      core/src/main/resources/com/github/weisj/darklaf/icons/progress/resume.svg
  6. 18
      core/src/main/resources/com/github/weisj/darklaf/icons/progress/step_passive.svg
  7. 18
      core/src/main/resources/com/github/weisj/darklaf/icons/progress/step_working.svg
  8. 26
      core/src/test/java/ui/label/LabelDemo.java
  9. 64
      core/src/test/java/ui/label/LabelDemoBase.java
  10. 61
      core/src/test/java/ui/label/LoadIndicator.java
  11. 12
      property-loader/src/main/java/com/github/weisj/darklaf/icons/DarkSVGIcon.java
  12. 4
      property-loader/src/main/java/com/github/weisj/darklaf/icons/RotatableIcon.java
  13. 41
      property-loader/src/main/java/com/github/weisj/darklaf/icons/RotateIcon.java
  14. 92
      property-loader/src/main/java/com/github/weisj/darklaf/icons/TwoIcon.java
  15. 32
      utils/src/main/java/com/github/weisj/darklaf/util/Alignment.java

69
core/src/main/java/com/github/weisj/darklaf/components/RotatableIconAnimator.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 com.github.weisj.darklaf.components;
import java.awt.event.ActionEvent;
import javax.swing.*;
import com.github.weisj.darklaf.icons.RotatableIcon;
import com.github.weisj.darklaf.util.Alignment;
public class RotatableIconAnimator extends Timer {
private final RotatableIcon icon;
private final JComponent parent;
private final int frameCount;
private int frame;
public RotatableIconAnimator(final RotatableIcon icon, final JComponent parent) {
this(Alignment.values().length, icon, parent);
}
public RotatableIconAnimator(final int frames, final RotatableIcon icon, final JComponent parent) {
super(100, null);
if (icon == null) throw new IllegalArgumentException("Icon is null");
if (parent == null) throw new IllegalArgumentException("Component is null");
addActionListener(this::onAction);
setRepeats(true);
this.icon = icon;
this.frameCount = frames;
this.parent = parent;
}
public void resume() {
start();
}
public void onAction(final ActionEvent e) {
icon.setRotation(Math.PI * 2 * (((double) frame) / frameCount));
parent.repaint();
frame = (frame + 1) % frameCount;
}
public void suspend() {
stop();
}
}

127
core/src/main/java/com/github/weisj/darklaf/components/loading/LoadingIndicator.java

@ -0,0 +1,127 @@
/*
* 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 com.github.weisj.darklaf.components.loading;
import javax.swing.*;
import com.github.weisj.darklaf.components.RotatableIconAnimator;
import com.github.weisj.darklaf.icons.EmptyIcon;
import com.github.weisj.darklaf.icons.RotatableIcon;
import com.github.weisj.darklaf.icons.TwoIcon;
import com.github.weisj.darklaf.util.DarkUIUtil;
/**
* Label that functions as an loading indicator.
*/
public class LoadingIndicator extends JLabel {
private final RotatableIcon loadIcon = new RotatableIcon(DarkUIUtil.ICON_LOADER.getIcon("progress/step_working.svg"));
private final Icon pausedIcon = DarkUIUtil.ICON_LOADER.getIcon("progress/step_passive.svg");
private final Icon emptyIcon = EmptyIcon.create(loadIcon.getIconWidth(), loadIcon.getIconHeight());
private final TwoIcon displayIcon = new TwoIcon(loadIcon, null);
private final RotatableIconAnimator animator = new RotatableIconAnimator(8, loadIcon, this);
private boolean running;
public LoadingIndicator(final String text, final Icon icon, final int horizontalAlignment) {
super(text, icon, horizontalAlignment);
displayIcon.setIconGap(getIconTextGap());
}
public LoadingIndicator(final String text, final int horizontalAlignment) {
this(text, null, horizontalAlignment);
}
public LoadingIndicator(final String text) {
this(text, null, LEADING);
}
public LoadingIndicator(final Icon image, final int horizontalAlignment) {
this(null, image, horizontalAlignment);
}
public LoadingIndicator(final Icon image) {
this(null, image, CENTER);
}
public LoadingIndicator() {
this("", null, LEADING);
}
/**
* Sets whether the icon should be animated.
*
* @param running true if animated.
*/
public void setRunning(final boolean running) {
this.running = running;
setAnimatorState(running);
}
private void setAnimatorState(final boolean running) {
if (running == animator.isRunning()) return;
if (running) {
animator.resume();
} else {
animator.suspend();
}
repaint();
}
@Override
public void setEnabled(final boolean enabled) {
super.setEnabled(enabled);
setAnimatorState(isRunning());
}
/**
* Returns whether the loading icon is animated and visible.
*
* @see #setRunning(boolean)
* @return true if animated and visible.
*/
public boolean isRunning() {
return running && isEnabled();
}
@Override
public void setIconTextGap(final int iconTextGap) {
super.setIconTextGap(iconTextGap);
displayIcon.setIconGap(getIconTextGap());
}
@Override
public Icon getIcon() {
displayIcon.setLeftIcon(running ? loadIcon : pausedIcon);
displayIcon.setRightIcon(super.getIcon());
return displayIcon;
}
@Override
public Icon getDisabledIcon() {
displayIcon.setLeftIcon(emptyIcon);
displayIcon.setRightIcon(super.getDisabledIcon());
return displayIcon;
}
}

25
core/src/main/java/com/github/weisj/darklaf/graphics/Animator.java

@ -66,18 +66,22 @@ public abstract class Animator {
this.repeatable = repeatable;
this.forward = forward;
currentFrame = forward ? 0 : totalFrames;
resetTime();
reset();
}
public void reset() {
currentFrame = 0;
private void resetTime() {
startTime = -1;
}
public void reset() {
currentFrame %= totalFrames;
if (!forward) currentFrame = totalFrames - currentFrame;
}
private static ScheduledExecutorService createScheduler() {
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1, r -> {
final Thread thread = new Thread(r, "Darcula Animations");
final Thread thread = new Thread(r, "Animations Thread");
thread.setDaemon(true);
thread.setPriority(Thread.MAX_PRIORITY);
return thread;
@ -89,7 +93,8 @@ public abstract class Animator {
}
public void suspend() {
startTime = -1;
resetTime();
reset();
stopTicker();
}
@ -119,10 +124,11 @@ public abstract class Animator {
@Override
public void run() {
if (isScheduled.compareAndSet(false, true) && !isDisposed()) {
if (!isScheduled.get() && !isDisposed()) {
isScheduled.set(true);
SwingUtilities.invokeLater(() -> {
isScheduled.set(false);
onTick();
isScheduled.set(false);
});
}
}
@ -136,7 +142,6 @@ public abstract class Animator {
private void animationDone() {
stopTicker();
SwingUtilities.invokeLater(this::paintCycleEnd);
}
@ -145,11 +150,11 @@ public abstract class Animator {
}
private void onTick() {
if (isDisposed()) return;
if (isDisposed() || ticker == null) return;
if (startTime == -1) {
startTime = System.currentTimeMillis();
stopTime = startTime + cycleDuration * (totalFrames - currentFrame) / totalFrames;
stopTime = startTime + (cycleDuration * (totalFrames - currentFrame)) / totalFrames;
}
final double passedTime = System.currentTimeMillis() - startTime;

12
core/src/main/resources/com/github/weisj/darklaf/icons/progress/pause.svg

@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14">
<defs id="colors">
<linearGradient id="Icons.pause.color">
<stop offset="0" stop-color="#AFB1B3"/>
<stop offset="1" stop-color="#AFB1B3"/>
</linearGradient>
</defs>
<g fill="url(#Icons.pause.color)" fill-rule="evenodd" transform="translate(2)">
<rect width="3.5" height="14"/>
<rect width="3.5" height="14" x="6.5"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 473 B

9
core/src/main/resources/com/github/weisj/darklaf/icons/progress/resume.svg

@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14">
<defs id="colors">
<linearGradient id="Icons.resume.color">
<stop offset="0" stop-color="#AFB1B3"/>
<stop offset="1" stop-color="#AFB1B3"/>
</linearGradient>
</defs>
<polygon fill="url(#Icons.resume.color)" fill-rule="evenodd" points="7 1 14 13 0 13" transform="rotate(90 7 7)"/>
</svg>

After

Width:  |  Height:  |  Size: 423 B

18
core/src/main/resources/com/github/weisj/darklaf/icons/progress/step_passive.svg

@ -0,0 +1,18 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<defs id="colors">
<linearGradient id="Icons.step.passive.color">
<stop offset="0" stop-color="#AFB1B3"/>
<stop offset="1" stop-color="#AFB1B3"/>
</linearGradient>
</defs>
<g fill="url(#Icons.step.passive.color)" fill-opacity=".5" fill-rule="evenodd" transform="translate(1 1)">
<rect width="2" height="4" x="2.471" y="1.471" transform="rotate(-45 3.471 3.471)"/>
<rect width="4" height="2" y="6"/>
<rect width="2" height="4" x="2.471" y="8.531" transform="rotate(45 3.471 10.531)"/>
<rect width="2" height="4" x="6" y="10"/>
<rect width="2" height="4" x="9.531" y="8.531" transform="rotate(-45 10.531 10.531)"/>
<rect width="4" height="2" x="10" y="6"/>
<rect width="2" height="4" x="9.531" y="1.471" transform="rotate(45 10.531 3.471)"/>
<rect width="2" height="4" x="6"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 991 B

18
core/src/main/resources/com/github/weisj/darklaf/icons/progress/step_working.svg

@ -0,0 +1,18 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<defs id="colors">
<linearGradient id="Icons.step.working.color">
<stop offset="0" stop-color="#AFB1B3"/>
<stop offset="1" stop-color="#AFB1B3"/>
</linearGradient>
</defs>
<g fill="url(#Icons.step.working.color)" fill-rule="evenodd" transform="translate(1 1)">
<rect width="2" height="4" x="2.471" y="1.471" opacity=".93" transform="rotate(-45 3.471 3.471)"/>
<rect width="4" height="2" y="6" opacity=".78"/>
<rect width="2" height="4" x="2.471" y="8.531" opacity=".69" transform="rotate(45 3.471 10.531)"/>
<rect width="2" height="4" x="6" y="10" opacity=".62"/>
<rect width="2" height="4" x="9.531" y="8.531" opacity=".48" transform="rotate(-45 10.531 10.531)"/>
<rect width="4" height="2" x="10" y="6" opacity=".38"/>
<rect width="2" height="4" x="9.531" y="1.471" opacity=".3" transform="rotate(45 10.531 3.471)"/>
<rect width="2" height="4" x="6"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

26
core/src/test/java/ui/label/LabelDemo.java

@ -29,36 +29,16 @@ import java.awt.*;
import javax.swing.*;
import ui.ComponentDemo;
import ui.DemoPanel;
import ui.DemoResources;
public class LabelDemo implements ComponentDemo {
public class LabelDemo extends LabelDemoBase<JLabel> {
public static void main(final String[] args) {
ComponentDemo.showDemo(new LabelDemo());
}
@Override
public JComponent createComponent() {
Icon icon = DemoResources.FOLDER_ICON;
JLabel label = new JLabel("Test Label", icon, JLabel.LEFT);
DemoPanel panel = new DemoPanel(label);
JPanel controlPanel = panel.addControls();
controlPanel.add(new JCheckBox("enabled") {
{
setSelected(label.isEnabled());
addActionListener(e -> label.setEnabled(isSelected()));
}
});
controlPanel.add(new JCheckBox("LeftToRight") {
{
setSelected(label.getComponentOrientation().isLeftToRight());
addActionListener(e -> label.setComponentOrientation(isSelected() ? ComponentOrientation.LEFT_TO_RIGHT
: ComponentOrientation.RIGHT_TO_LEFT));
}
});
return panel;
protected JLabel createLabel() {
return new JLabel("Test Label", DemoResources.FOLDER_ICON, JLabel.LEFT);
}
@Override

64
core/src/test/java/ui/label/LabelDemoBase.java

@ -0,0 +1,64 @@
/*
* 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 ui.label;
import java.awt.*;
import javax.swing.*;
import ui.ComponentDemo;
import ui.DemoPanel;
public abstract class LabelDemoBase<T extends JLabel> implements ComponentDemo {
@Override
public JComponent createComponent() {
T label = createLabel();
DemoPanel panel = new DemoPanel(label);
JPanel controlPanel = createControlPanel(panel, label);
return panel;
}
protected JPanel createControlPanel(final DemoPanel panel, final T label) {
JPanel controlPanel = panel.addControls();
controlPanel.add(new JCheckBox("enabled") {
{
setSelected(label.isEnabled());
addActionListener(e -> label.setEnabled(isSelected()));
}
});
controlPanel.add(new JCheckBox("LeftToRight") {
{
setSelected(label.getComponentOrientation().isLeftToRight());
addActionListener(e -> label.setComponentOrientation(isSelected() ? ComponentOrientation.LEFT_TO_RIGHT
: ComponentOrientation.RIGHT_TO_LEFT));
}
});
return controlPanel;
}
protected abstract T createLabel();
}

61
core/src/test/java/ui/label/LoadIndicator.java

@ -0,0 +1,61 @@
/*
* 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 ui.label;
import javax.swing.*;
import ui.ComponentDemo;
import ui.DemoPanel;
import ui.DemoResources;
import com.github.weisj.darklaf.components.loading.LoadingIndicator;
public class LoadIndicator extends LabelDemoBase<LoadingIndicator> {
public static void main(final String[] args) {
ComponentDemo.showDemo(new LoadIndicator());
}
@Override
protected JPanel createControlPanel(final DemoPanel panel, final LoadingIndicator label) {
JPanel controls = super.createControlPanel(panel, label);
controls.add(new JCheckBox("running") {
{
setSelected(label.isRunning());
addActionListener(e -> label.setRunning(isSelected()));
}
});
return controls;
}
protected LoadingIndicator createLabel() {
return new LoadingIndicator("Load Indicator", DemoResources.FOLDER_ICON, JLabel.LEFT);
}
@Override
public String getTitle() {
return "Load Indicator Demo";
}
}

12
property-loader/src/main/java/com/github/weisj/darklaf/icons/DarkSVGIcon.java

@ -41,7 +41,7 @@ import com.kitfox.svg.app.beans.SVGIcon;
* @author Jannis Weis
* @since 2019
*/
public class DarkSVGIcon implements DerivableIcon<DarkSVGIcon>, Serializable {
public class DarkSVGIcon implements DerivableIcon<DarkSVGIcon>, RotateIcon, Serializable {
private static final Logger LOGGER = LogUtil.getLogger(DarkSVGIcon.class);
private final Dimension size;
@ -99,15 +99,7 @@ public class DarkSVGIcon implements DerivableIcon<DarkSVGIcon>, Serializable {
return new SVGIcon();
}
/**
* Paint the icon with rotation.
*
* @param c the parent component.
* @param g the graphics object.
* @param x the x coordinate
* @param y the y coordinate
* @param rotation the rotation in radians.
*/
@Override
public void paintIcon(final Component c, final Graphics g, final int x, final int y,
final double rotation) {
ensureLoaded();

4
property-loader/src/main/java/com/github/weisj/darklaf/icons/RotatableIcon.java

@ -51,8 +51,8 @@ public class RotatableIcon implements Icon {
@Override
public void paintIcon(final Component c, final Graphics g, final int x, final int y) {
if (icon instanceof DarkSVGIcon) {
((DarkSVGIcon) icon).paintIcon(c, g, x, y, getAngle());
if (icon instanceof RotateIcon) {
((RotateIcon) icon).paintIcon(c, g, x, y, getAngle());
} else if (icon != null) {
Graphics2D g2 = (Graphics2D) g.create();
AffineTransform transform = new AffineTransform();

41
property-loader/src/main/java/com/github/weisj/darklaf/icons/RotateIcon.java

@ -0,0 +1,41 @@
/*
* 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 com.github.weisj.darklaf.icons;
import java.awt.*;
public interface RotateIcon {
/**
* Paint the icon with rotation.
*
* @param c the parent component.
* @param g the graphics object.
* @param x the x coordinate
* @param y the y coordinate
* @param rotation the rotation in radians.
*/
void paintIcon(Component c, Graphics g, int x, int y, double rotation);
}

92
property-loader/src/main/java/com/github/weisj/darklaf/icons/TwoIcon.java

@ -0,0 +1,92 @@
/*
* 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 com.github.weisj.darklaf.icons;
import java.awt.*;
import javax.swing.*;
public class TwoIcon implements Icon {
private int iconGap = 2;
private Icon leftIcon;
private Icon rightIcon;
public TwoIcon(final Icon leftIcon, final Icon rightIcon) {
this(leftIcon, rightIcon, 2);
}
public TwoIcon(final Icon leftIcon, final Icon rightIcon, final int iconGap) {
setLeftIcon(leftIcon);
setRightIcon(rightIcon);
this.iconGap = iconGap;
}
public void setIconGap(final int iconGap) {
this.iconGap = iconGap;
}
public void setLeftIcon(final Icon leftIcon) {
this.leftIcon = leftIcon != null ? leftIcon : EmptyIcon.create(0);
}
public void setRightIcon(final Icon rightIcon) {
this.rightIcon = rightIcon != null ? rightIcon : EmptyIcon.create(0);
}
public Icon getLeftIcon() {
return leftIcon;
}
public Icon getRightIcon() {
return rightIcon;
}
@Override
public void paintIcon(final Component c, final Graphics g, final int x, final int y) {
int mid = getIconHeight() / 2;
boolean ltr = c.getComponentOrientation().isLeftToRight();
Icon left = ltr ? leftIcon : rightIcon;
Icon right = ltr ? rightIcon : leftIcon;
int y1 = y + mid - left.getIconHeight() / 2;
int y2 = y + mid - right.getIconHeight() / 2;
leftIcon.paintIcon(c, g, x, y1);
rightIcon.paintIcon(c, g, x + left.getIconWidth() + iconGap, y2);
}
@Override
public int getIconWidth() {
int l = leftIcon.getIconWidth();
int r = rightIcon.getIconWidth();
int gap = 0;
if (l != 0 && r != 0) gap = iconGap;
return l + r + gap;
}
@Override
public int getIconHeight() {
return Math.max(leftIcon.getIconHeight(), rightIcon.getIconHeight());
}
}

32
utils/src/main/java/com/github/weisj/darklaf/util/Alignment.java

@ -304,4 +304,36 @@ public enum Alignment {
public boolean isWest(final boolean includePure) {
return (this == Alignment.WEST && includePure) || this == Alignment.NORTH_WEST || this == Alignment.SOUTH_WEST;
}
public double getAngle() {
double angle = 0.0;
switch (this) {
case NORTH :
case CENTER :
angle = 0.0;
break;
case SOUTH :
angle = 180.0;
break;
case EAST :
angle = 90.0;
break;
case WEST :
angle = 270.0;
break;
case NORTH_EAST :
angle = 45.0;
break;
case NORTH_WEST :
angle = 315.0;
break;
case SOUTH_EAST :
angle = 135.0;
break;
case SOUTH_WEST :
angle = 225.0;
break;
}
return Math.toRadians(angle);
}
}

Loading…
Cancel
Save