app icon for tests runner

This commit is contained in:
Kirill Kalishev
2010-05-19 21:20:16 +04:00
parent ecc1f184c5
commit 30d4a4d772
4 changed files with 166 additions and 33 deletions
@@ -17,9 +17,11 @@ package com.intellij.ui;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.wm.IdeFrame;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public abstract class AppIcon {
@@ -29,9 +31,13 @@ public abstract class AppIcon {
static AppIcon ourMacImpl;
static AppIcon ourEmptyImpl;
public abstract void setProgress(double value, boolean isOk);
public abstract void setProgress(IdeFrame frame, Object processId, AppIconScheme.Progress scheme, double value, boolean isOk);
public abstract void hideProgress();
public abstract void hideProgress(IdeFrame frame, Object processId);
public abstract void setBadge(String text);
public abstract void requestAttention(boolean critical);
public static AppIcon getInstance() {
if (ourMacImpl == null) {
@@ -47,86 +53,118 @@ public abstract class AppIcon {
}
}
private static class MacAppIcon extends AppIcon {
private static BufferedImage myAppImage;
private static BufferedImage myCurrentImage;
private Object myCurrentProcessId;
private boolean myProgressShown;
private double myUpdateFraction = 0.05d;
private double myLastValue;
private MacAppIcon() {
private BufferedImage getAppImage() {
try {
Object app = getApp().invoke(null);
if (myAppImage != null) return myAppImage;
Object app = getApp();
Image appImage = (Image)getAppMethod("getDockIconImage").invoke(app);
if (appImage == null) return null;
int width = appImage.getWidth(null);
int height = appImage.getHeight(null);
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.drawImage(appImage, null, null);
myAppImage = img;
}
catch (Exception e) {
LOG.error(e);
}
return myAppImage;
}
@Override
public void setBadge(String text) {
try {
getAppMethod("setDockIconBadge", String.class).invoke(getApp(), text);
}
catch (Exception e) {
LOG.error(e);
}
}
private Method getAppMethod(final String name, Class... args) throws NoSuchMethodException, ClassNotFoundException {
return getAppClass().getMethod(name, args);
}
private Method getApp() throws NoSuchMethodException, ClassNotFoundException {
return getAppClass().getMethod("getApplication");
}
private Class<?> getAppClass() throws ClassNotFoundException {
return Class.forName("com.apple.eawt.Application");
@Override
public void requestAttention(boolean critical) {
try {
getAppMethod("requestUserAttention", Boolean.class).invoke(getApp(), Boolean.valueOf(critical));
}
catch (NoSuchMethodException e) {
return;
} catch (Exception e) {
LOG.error(e);
}
}
@Override
public void hideProgress() {
public void hideProgress(IdeFrame frame, Object processId) {
if (getAppImage() == null) return;
try {
if (myProgressShown) {
setDockIcon(myAppImage);
if (myCurrentProcessId != null && myCurrentProcessId.equals(processId)) {
setDockIcon(getAppImage());
}
}
finally {
myProgressShown = false;
myCurrentProcessId = null;
myLastValue = 0;
}
}
public void setProgress(double progress, boolean isOk) {
public void setProgress(IdeFrame frame, Object processId, AppIconScheme.Progress scheme, double value, boolean isOk) {
if (getAppImage() == null) return;
if (myCurrentProcessId != null && !myCurrentProcessId.equals(processId)) return;
myCurrentProcessId = processId;
if (Math.abs(myLastValue - value) < myUpdateFraction) return;
try {
int progressHeight = 45;
int progressHeight = 65;
int xInset = 30;
int yInset = 10;
int yInset = 25;
int arc = 25;
Rectangle progressRec = new Rectangle(new Point(xInset, myAppImage.getHeight() - yInset - progressHeight),
new Dimension(myAppImage.getWidth() - xInset * 2, progressHeight));
myCurrentImage = new BufferedImage(myAppImage.getWidth(), myAppImage.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g = myCurrentImage.createGraphics();
BufferedImage current = new BufferedImage(myAppImage.getWidth(), myAppImage.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g = current.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.drawImage(myAppImage, null, null);
g.drawImage(getAppImage(), null, null);
g.setColor(Color.black);
g.fillRoundRect(progressRec.x, progressRec.y, progressRec.width, progressRec.height, arc, arc);
g.setColor(isOk ? Color.green : Color.red);
g.setColor(isOk ? scheme.getOkColor() : scheme.getErrorColor());
int currentWidth = (int)Math.ceil(progressRec.width * progress);
int currentWidth = (int)Math.ceil(progressRec.width * value);
g.fillRoundRect(progressRec.x, progressRec.y, currentWidth, progressRec.height, arc, arc);
setDockIcon(myCurrentImage);
setDockIcon(current);
myLastValue = value;
}
catch (Exception e) {
LOG.error(e);
} finally {
myProgressShown = true;
myCurrentProcessId = null;
}
}
@@ -138,15 +176,36 @@ public abstract class AppIcon {
LOG.error(e);
}
}
private Method getAppMethod(final String name, Class... args) throws NoSuchMethodException, ClassNotFoundException {
return getAppClass().getMethod(name, args);
}
private Object getApp() throws NoSuchMethodException, ClassNotFoundException, InvocationTargetException, IllegalAccessException {
return getAppClass().getMethod("getApplication").invoke(null);
}
private Class<?> getAppClass() throws ClassNotFoundException {
return Class.forName("com.apple.eawt.Application");
}
}
private static class EmptyIcon extends AppIcon {
@Override
public void setProgress(double value, boolean isOk) {
public void setProgress(IdeFrame frame, Object processId, AppIconScheme.Progress scheme, double value, boolean isOk) {
}
@Override
public void hideProgress() {
public void hideProgress(IdeFrame frame, Object processId) {
}
@Override
public void setBadge(String text) {
}
@Override
public void requestAttention(boolean critical) {
}
}
@@ -0,0 +1,49 @@
/*
* Copyright 2000-2010 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.ui;
import java.awt.*;
public class AppIconScheme {
public interface Progress {
static final Progress TESTS = new Progress() {
public Color getOkColor() {
return Color.green;
}
public Color getErrorColor() {
return Color.red;
}
};
static final Progress BUILD = new Progress() {
public Color getOkColor() {
return Color.blue;
}
public Color getErrorColor() {
return Color.red;
}
};
Color getOkColor();
Color getErrorColor();
}
}
@@ -24,15 +24,19 @@ import com.intellij.execution.junit2.ui.model.JUnitAdapter;
import com.intellij.execution.junit2.ui.model.JUnitRunningModel;
import com.intellij.execution.testframework.Filter;
import com.intellij.execution.testframework.AbstractTestProxy;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.rt.execution.junit.states.PoolOfTestStates;
import javax.swing.*;
import com.intellij.ui.AppIcon;
import com.intellij.ui.AppIconScheme;
import org.jetbrains.annotations.NonNls;
public class TestProgress extends DefaultBoundedRangeModel {
public class TestProgress extends DefaultBoundedRangeModel implements Disposable {
private static final Logger LOG = Logger.getInstance("#com.intellij.execution.junit2.ui.TestProgress");
private static final String TESTS = "tests";
private int myProblemsCounter = 0;
private TestProxy myCurrentState = null;
private final MyJUnitListener myListener = new MyJUnitListener();
@@ -120,4 +124,24 @@ public class TestProgress extends DefaultBoundedRangeModel {
myMissingChildren--;
}
}
@Override
public void setValue(int n) {
super.setValue(n);
AppIcon icon = AppIcon.getInstance();
if (n < getMaximum()) {
icon.setProgress(null, TESTS, AppIconScheme.Progress.TESTS, (double)n / (double)getMaximum(), myProblemsCounter == 0);
} else {
icon.hideProgress(null, TESTS);
if (myProblemsCounter > 0) {
icon.setBadge(String.valueOf(myProblemsCounter));
icon.requestAttention(false);
}
}
}
public void dispose() {
AppIcon.getInstance().hideProgress(null, TESTS);
AppIcon.getInstance().setBadge(null);
}
}
@@ -57,6 +57,7 @@ public class JUnitRunningModel implements TestFrameworkRunningModel {
myProperties = properties;
myRoot.setEventsConsumer(myNotifier);
myProgress = new TestProgress(this);
Disposer.register(this, myProgress);
Disposer.register(this, myTreeListener);
Disposer.register(this, new Disposable() {
public void dispose() {