blob: 26220fb464d7d6e851a212dc8061f435e691768e [file] [log] [blame]
/*
* Copyright 2000-2013 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.openapi.wm.impl.status;
import com.intellij.concurrency.JobScheduler;
import com.intellij.openapi.wm.CustomStatusBarWidget;
import com.intellij.openapi.wm.StatusBar;
import com.intellij.openapi.wm.StatusBarWidget;
import com.intellij.ui.Gray;
import com.intellij.ui.JBColor;
import com.intellij.ui.UIBundle;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
public class MemoryUsagePanel extends JButton implements CustomStatusBarWidget {
@NonNls public static final String WIDGET_ID = "Memory";
private static final int MEGABYTE = 1024 * 1024;
@NonNls private static final String SAMPLE_STRING;
static {
long maxMemory = Math.min(Runtime.getRuntime().maxMemory() / MEGABYTE, 9999);
SAMPLE_STRING = maxMemory + " of " + maxMemory + "M ";
}
private static final int HEIGHT = 16;
private static final Color USED_COLOR_1 = new JBColor(Gray._185, Gray._150);
private static final Color USED_COLOR_2 = new JBColor(Gray._145, Gray._120);
private static final Color UNUSED_COLOR_1 = new JBColor(Gray._200.withAlpha(100), Gray._120);
private static final Color UNUSED_COLOR_2 = new JBColor(Gray._150.withAlpha(130), Gray._100);
private static final Color UNUSED_COLOR_3 = Gray._175;
private long myLastTotal = -1;
private long myLastUsed = -1;
private ScheduledFuture<?> myFuture;
private Image myBufferedImage;
private boolean myWasPressed;
public MemoryUsagePanel() {
setOpaque(false);
setFocusable(false);
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.gc();
updateState();
}
});
setBorder(StatusBarWidget.WidgetBorder.INSTANCE);
updateUI();
}
@Override
public void dispose() {
myFuture.cancel(true);
myFuture = null;
}
@Override
public void install(@NotNull StatusBar statusBar) { }
@Override
@Nullable
public WidgetPresentation getPresentation(@NotNull PlatformType type) {
return null;
}
@Override
@NotNull
public String ID() {
return WIDGET_ID;
}
public void setShowing(final boolean showing) {
if (showing != isVisible()) {
setVisible(showing);
revalidate();
}
}
@Override
public void updateUI() {
super.updateUI();
setFont(getWidgetFont());
}
private static Font getWidgetFont() {
return UIUtil.getLabelFont().deriveFont(11.0f);
}
@Override
public JComponent getComponent() {
return this;
}
@Override
public void paintComponent(final Graphics g) {
final boolean pressed = getModel().isPressed();
final boolean stateChanged = myWasPressed != pressed;
myWasPressed = pressed;
if (myBufferedImage == null || stateChanged) {
final Dimension size = getSize();
final Insets insets = getInsets();
myBufferedImage = UIUtil.createImage(size.width, size.height, BufferedImage.TYPE_INT_ARGB);
final Graphics2D g2 = (Graphics2D)myBufferedImage.getGraphics().create();
final Runtime rt = Runtime.getRuntime();
final long maxMem = rt.maxMemory();
final long allocatedMem = rt.totalMemory();
final long unusedMem = rt.freeMemory();
final long usedMem = allocatedMem - unusedMem;
final int totalBarLength = size.width - insets.left - insets.right;
final int usedBarLength = (int)(totalBarLength * usedMem / maxMem);
final int unusedBarLength = (int)(totalBarLength * unusedMem / maxMem);
final int barHeight = HEIGHT;
final int yOffset = (size.height - barHeight) / 2;
final int xOffset = insets.left;
// background
if (!UIUtil.isUnderAquaLookAndFeel()) {
g2.setColor(UIUtil.getControlColor());
}
else {
g2.setPaint(UIUtil.getGradientPaint(0, 0, new JBColor(Gray._190, Gray._120), 0, barHeight, new JBColor(Gray._230, Gray._160)));
}
g2.fillRect(xOffset, yOffset, totalBarLength, barHeight);
// gauge (used)
setGradient(g2, pressed, barHeight, USED_COLOR_1, USED_COLOR_2);
g2.fillRect(xOffset, yOffset, usedBarLength, barHeight);
// gauge (unused)
setGradient(g2, pressed, barHeight, UNUSED_COLOR_1, UNUSED_COLOR_2);
g2.fillRect(xOffset + usedBarLength, yOffset, unusedBarLength, barHeight);
if (!UIUtil.isUnderDarcula()) {
g2.setColor(UNUSED_COLOR_3);
g2.drawLine(xOffset + usedBarLength + unusedBarLength, yOffset, xOffset + usedBarLength + unusedBarLength, barHeight);
}
// frame
if (!UIUtil.isUnderDarcula()) {
g2.setColor(USED_COLOR_2);
g2.drawRect(xOffset, yOffset, totalBarLength - 1, barHeight - 1);
}
// label
g2.setFont(getFont());
final long used = usedMem / MEGABYTE;
final long total = maxMem / MEGABYTE;
final String info = UIBundle.message("memory.usage.panel.message.text", used, total);
final FontMetrics fontMetrics = g.getFontMetrics();
final int infoWidth = fontMetrics.charsWidth(info.toCharArray(), 0, info.length());
final int infoHeight = fontMetrics.getAscent();
UIUtil.applyRenderingHints(g2);
g2.setColor(UIUtil.getLabelForeground());
g2.drawString(info, xOffset + (totalBarLength - infoWidth) / 2, yOffset + infoHeight + (barHeight - infoHeight) / 2 - 1);
g2.dispose();
}
UIUtil.drawImage(g, myBufferedImage, 0, 0, null);
}
private static void setGradient(Graphics2D g2, boolean invert, int height, Color start, Color end) {
if (UIUtil.isUnderDarcula()) {
start = start.darker();
end = end.darker();
}
if (invert) {
g2.setPaint(UIUtil.getGradientPaint(0, 0, end, 0, height, start));
}
else {
g2.setPaint(UIUtil.getGradientPaint(0, 0, start, 0, height, end));
}
}
@Override
public Dimension getPreferredSize() {
final Insets insets = getInsets();
int width = getFontMetrics(getWidgetFont()).stringWidth(SAMPLE_STRING) + insets.left + insets.right + 2;
int height = getFontMetrics(getWidgetFont()).getHeight() + insets.top + insets.bottom + 2;
return new Dimension(width, height);
}
@Override
public Dimension getMinimumSize() {
return getPreferredSize();
}
@Override
public Dimension getMaximumSize() {
return getPreferredSize();
}
/**
* Invoked when enclosed frame is being shown.
*/
@Override
public void addNotify() {
myFuture = JobScheduler.getScheduler().scheduleWithFixedDelay(new Runnable() {
public void run() {
if (isDisplayable()) {
updateState();
}
}
}, 1, 5, TimeUnit.SECONDS);
super.addNotify();
}
private void updateState() {
if (!isShowing()) {
return;
}
final Runtime runtime = Runtime.getRuntime();
final long total = runtime.totalMemory() / MEGABYTE;
final long used = total - runtime.freeMemory() / MEGABYTE;
if (total != myLastTotal || used != myLastUsed) {
myLastTotal = total;
myLastUsed = used;
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
public void run() {
myBufferedImage = null;
repaint();
}
});
setToolTipText(UIBundle.message("memory.usage.panel.statistics.message", total, used));
}
}
}