blob: cc41994f002379e069baff0d56835e4c0b6139c1 [file] [log] [blame]
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.util.ui;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.util.Disposer;
import javax.swing.*;
import java.awt.*;
/**
* @author Kirill Kalishev
* @author Konstantin Bulenkov
*/
public class AnimatedIcon extends JComponent implements Disposable {
private final Icon[] myIcons;
private final Dimension myPrefSize = new Dimension();
//no need to make it volatile, all r/w operations are from EDT
private int myCurrentIconIndex;
private final Icon myPassiveIcon;
private final Icon myEmptyPassiveIcon;
private boolean myPaintPassive = true;
private boolean myRunning = true;
protected final Animator myAnimator;
private final String myName;
//private boolean myPaintingBgNow;
public AnimatedIcon(final String name, Icon[] icons, Icon passiveIcon, int cycleLength) {
myName = name;
myIcons = icons.length == 0 ? new Icon[]{passiveIcon} : icons;
myPassiveIcon = passiveIcon;
for (Icon each : icons) {
myPrefSize.width = Math.max(each.getIconWidth(), myPrefSize.width);
myPrefSize.height = Math.max(each.getIconHeight(), myPrefSize.height);
}
myPrefSize.width = Math.max(passiveIcon.getIconWidth(), myPrefSize.width);
myPrefSize.height = Math.max(passiveIcon.getIconHeight(), myPrefSize.height);
myAnimator = new Animator(myName, icons.length, cycleLength, true) {
@Override
public void paintNow(final int frame, final int totalFrames, final int cycle) {
final int len = myIcons.length;
myCurrentIconIndex = frame < 0 ? 0 : frame >= len ? len - 1 : frame;
paintImmediately(0, 0, getWidth(), getHeight());
}
};
if (icons.length > 0) {
myEmptyPassiveIcon = EmptyIcon.create(icons[0]);
} else {
myEmptyPassiveIcon = EmptyIcon.ICON_0;
}
setOpaque(false);
}
public void setPaintPassiveIcon(boolean paintPassive) {
myPaintPassive = paintPassive;
}
private boolean ensureAnimation(boolean running) {
boolean changes = myAnimator.isRunning() != running;
if (running) {
myAnimator.resume();
} else {
myAnimator.suspend();
}
return changes;
}
@Override
public void addNotify() {
super.addNotify();
if (myRunning) {
ensureAnimation(true);
}
}
@Override
public void removeNotify() {
super.removeNotify();
ensureAnimation(false);
}
public void resume() {
myRunning = true;
ensureAnimation(true);
}
public void suspend() {
myRunning = false;
if (ensureAnimation(false)) {
repaint();
}
}
@Override
public void dispose() {
Disposer.dispose(myAnimator);
}
@Override
public Dimension getPreferredSize() {
final Insets insets = getInsets();
return new Dimension(myPrefSize.width + insets.left + insets.right, myPrefSize.height + insets.top + insets.bottom);
}
@Override
public Dimension getMinimumSize() {
return getPreferredSize();
}
@Override
public Dimension getMaximumSize() {
return getPreferredSize();
}
@Override
protected void paintComponent(Graphics g) {
//if (myPaintingBgNow) return;
if (isOpaque()) {
final Container parent = getParent();
JComponent opaque = null;
if (parent instanceof JComponent) {
opaque = (JComponent)UIUtil.findNearestOpaque((JComponent)parent);
}
Color bg = opaque != null ? opaque.getBackground() : UIUtil.getPanelBackground();
g.setColor(bg);
g.fillRect(0, 0, getWidth(), getHeight());
}
Icon icon;
if (myAnimator.isRunning()) {
icon = myIcons[myCurrentIconIndex];
} else {
icon = getPassiveIcon();
}
final Dimension size = getSize();
int x = (size.width - icon.getIconWidth()) / 2;
int y = (size.height - icon.getIconHeight()) / 2;
paintIcon(g, icon, x, y);
//boolean lastPaintWasRunning = myAnimator.isRunning();
}
protected void paintIcon(Graphics g, Icon icon, int x, int y) {
icon.paintIcon(this, g, x, y);
}
protected Icon getPassiveIcon() {
return myPaintPassive ? myPassiveIcon : myEmptyPassiveIcon;
}
public boolean isRunning() {
return myAnimator.isRunning();
}
@Override
public String toString() {
return myName + " isRunning=" + myRunning + " isOpaque=" + isOpaque() + " paintPassive=" + myPaintPassive;
}
}