Better caching of images, better api (change graphic -> image) to make
more sense. Set the default image names to be static strings, so it's easier to know what they are without knowing specific details.
This commit is contained in:
parent
cdbf8a2a4d
commit
289e83ba63
|
@ -18,7 +18,6 @@ package dorkbox.notify;
|
||||||
import java.awt.Dialog;
|
import java.awt.Dialog;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Frame;
|
import java.awt.Frame;
|
||||||
import java.awt.Image;
|
|
||||||
import java.awt.Window;
|
import java.awt.Window;
|
||||||
import java.awt.event.ComponentEvent;
|
import java.awt.event.ComponentEvent;
|
||||||
import java.awt.event.ComponentListener;
|
import java.awt.event.ComponentListener;
|
||||||
|
@ -43,7 +42,7 @@ class AsDialog extends JDialog implements INotify {
|
||||||
|
|
||||||
// this is on the swing EDT
|
// this is on the swing EDT
|
||||||
@SuppressWarnings("NumericCastThatLosesPrecision")
|
@SuppressWarnings("NumericCastThatLosesPrecision")
|
||||||
AsDialog(final Notify notification, final Image image, final ImageIcon imageIcon, final Window container, final Theme theme) {
|
AsDialog(final Notify notification, final ImageIcon image, final Window container, final Theme theme) {
|
||||||
super(container, Dialog.ModalityType.MODELESS);
|
super(container, Dialog.ModalityType.MODELESS);
|
||||||
this.notification = notification;
|
this.notification = notification;
|
||||||
|
|
||||||
|
@ -60,7 +59,7 @@ class AsDialog extends JDialog implements INotify {
|
||||||
setTitle(notification.title);
|
setTitle(notification.title);
|
||||||
setResizable(false);
|
setResizable(false);
|
||||||
|
|
||||||
NotifyCanvas notifyCanvas = new NotifyCanvas(notification, imageIcon, theme);
|
NotifyCanvas notifyCanvas = new NotifyCanvas(notification, image, theme);
|
||||||
add(notifyCanvas);
|
add(notifyCanvas);
|
||||||
|
|
||||||
look = new LookAndFeel(this, notifyCanvas, notification, image, container.getBounds());
|
look = new LookAndFeel(this, notifyCanvas, notification, image, container.getBounds());
|
||||||
|
|
|
@ -18,7 +18,6 @@ package dorkbox.notify;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.GraphicsDevice;
|
import java.awt.GraphicsDevice;
|
||||||
import java.awt.GraphicsEnvironment;
|
import java.awt.GraphicsEnvironment;
|
||||||
import java.awt.Image;
|
|
||||||
import java.awt.MouseInfo;
|
import java.awt.MouseInfo;
|
||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
|
@ -42,7 +41,7 @@ class AsFrame extends JFrame implements INotify {
|
||||||
|
|
||||||
// this is on the swing EDT
|
// this is on the swing EDT
|
||||||
@SuppressWarnings("NumericCastThatLosesPrecision")
|
@SuppressWarnings("NumericCastThatLosesPrecision")
|
||||||
AsFrame(final Notify notification, final Image image, final ImageIcon imageIcon, final Theme theme) {
|
AsFrame(final Notify notification, final ImageIcon image, final Theme theme) {
|
||||||
this.notification = notification;
|
this.notification = notification;
|
||||||
|
|
||||||
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||||
|
@ -90,7 +89,7 @@ class AsFrame extends JFrame implements INotify {
|
||||||
.getBounds();
|
.getBounds();
|
||||||
|
|
||||||
|
|
||||||
NotifyCanvas notifyCanvas = new NotifyCanvas(notification, imageIcon, theme);
|
NotifyCanvas notifyCanvas = new NotifyCanvas(notification, image, theme);
|
||||||
getContentPane().add(notifyCanvas);
|
getContentPane().add(notifyCanvas);
|
||||||
|
|
||||||
look = new LookAndFeel(this, notifyCanvas, notification, image, bounds);
|
look = new LookAndFeel(this, notifyCanvas, notification, image, bounds);
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package dorkbox.notify;
|
package dorkbox.notify;
|
||||||
|
|
||||||
import java.awt.Image;
|
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
import java.awt.Window;
|
import java.awt.Window;
|
||||||
import java.awt.event.MouseAdapter;
|
import java.awt.event.MouseAdapter;
|
||||||
|
@ -25,6 +24,8 @@ import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
import javax.swing.ImageIcon;
|
||||||
|
|
||||||
import dorkbox.tweenengine.BaseTween;
|
import dorkbox.tweenengine.BaseTween;
|
||||||
import dorkbox.tweenengine.Tween;
|
import dorkbox.tweenengine.Tween;
|
||||||
import dorkbox.tweenengine.TweenCallback;
|
import dorkbox.tweenengine.TweenCallback;
|
||||||
|
@ -91,7 +92,7 @@ class LookAndFeel {
|
||||||
LookAndFeel(final Window parent,
|
LookAndFeel(final Window parent,
|
||||||
final NotifyCanvas notifyCanvas,
|
final NotifyCanvas notifyCanvas,
|
||||||
final Notify notification,
|
final Notify notification,
|
||||||
final Image image,
|
final ImageIcon image,
|
||||||
final Rectangle parentBounds) {
|
final Rectangle parentBounds) {
|
||||||
|
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
|
@ -123,7 +124,7 @@ class LookAndFeel {
|
||||||
anchorY = getAnchorY(position, parentBounds);
|
anchorY = getAnchorY(position, parentBounds);
|
||||||
|
|
||||||
if (image != null) {
|
if (image != null) {
|
||||||
parent.setIconImage(image);
|
parent.setIconImage(image.getImage());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
parent.setIconImage(SwingUtil.BLANK_ICON);
|
parent.setIconImage(SwingUtil.BLANK_ICON);
|
||||||
|
|
|
@ -21,6 +21,7 @@ import java.awt.image.BufferedImage;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.lang.ref.SoftReference;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -28,6 +29,7 @@ import javax.imageio.ImageIO;
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
|
|
||||||
import dorkbox.util.ActionHandler;
|
import dorkbox.util.ActionHandler;
|
||||||
|
import dorkbox.util.ImageUtil;
|
||||||
import dorkbox.util.LocationResolver;
|
import dorkbox.util.LocationResolver;
|
||||||
import dorkbox.util.Property;
|
import dorkbox.util.Property;
|
||||||
import dorkbox.util.SwingUtil;
|
import dorkbox.util.SwingUtil;
|
||||||
|
@ -55,6 +57,12 @@ import dorkbox.util.Version;
|
||||||
public final
|
public final
|
||||||
class Notify {
|
class Notify {
|
||||||
|
|
||||||
|
public static final String DIALOG_CONFIRM = "dialog-confirm.png";
|
||||||
|
|
||||||
|
public static final String DIALOG_INFORMATION = "dialog-information.png";
|
||||||
|
public static final String DIALOG_WARNING = "dialog-warning.png";
|
||||||
|
public static final String DIALOG_ERROR = "dialog-error.png";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the title font used by a notification.
|
* This is the title font used by a notification.
|
||||||
*/
|
*/
|
||||||
|
@ -79,8 +87,7 @@ class Notify {
|
||||||
@Property
|
@Property
|
||||||
public static String IMAGE_PATH = "resources";
|
public static String IMAGE_PATH = "resources";
|
||||||
|
|
||||||
private static Map<String, BufferedImage> imageCache = new HashMap<String, BufferedImage>(4);
|
private static Map<String, SoftReference<ImageIcon>> imageCache = new HashMap<String, SoftReference<ImageIcon>>(4);
|
||||||
private static Map<String, ImageIcon> imageIconCache = new HashMap<String, ImageIcon>(4);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the version number.
|
* Gets the version number.
|
||||||
|
@ -98,38 +105,69 @@ class Notify {
|
||||||
return new Notify();
|
return new Notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the size of the image to be used in the notification, which is a 48x48 pixel image.
|
||||||
|
*/
|
||||||
|
public static
|
||||||
|
int getImageSize() {
|
||||||
|
return 48;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permits one to override the default images for the dialogs. This is NOT thread safe, and must be performed BEFORE showing a
|
* Permits one to override the default images for the dialogs. This is NOT thread safe, and must be performed BEFORE showing a
|
||||||
* notification.
|
* notification.
|
||||||
* <p>
|
* <p>
|
||||||
* The image names are as follows:
|
* The image names are as follows:
|
||||||
* <p>
|
* <p>
|
||||||
* 'dialog-confirm.png' 'dialog-error.png' 'dialog-information.png' 'dialog-warning.png'
|
* 'Notify.DIALOG_CONFIRM' 'Notify.DIALOG_INFORMATION' 'Notify.DIALOG_WARNING' 'Notify.DIALOG_ERROR'
|
||||||
*
|
*
|
||||||
* @param imageName the name of the image, either your own if you want want it cached, or one of the above.
|
* @param imageName the name of the image, either your own if you want want it cached, or one of the above.
|
||||||
* @param image the BufferedImage that you want to cache.
|
* @param image the BufferedImage that you want to cache.
|
||||||
*/
|
*/
|
||||||
public static
|
public static
|
||||||
void setImagePath(String imageName, BufferedImage image) {
|
void overrideDefaultImage(String imageName, BufferedImage image) {
|
||||||
if (imageCache.containsKey(imageName)) {
|
if (imageCache.containsKey(imageName)) {
|
||||||
throw new RuntimeException("Unable to set an image that already has been set. This action must be done as soon as possible.");
|
throw new RuntimeException("Unable to set an image that already has been set. This action must be done as soon as possible.");
|
||||||
}
|
}
|
||||||
|
|
||||||
imageCache.put(imageName, image);
|
Image imageImmediate = ImageUtil.getImageImmediate(image);
|
||||||
|
|
||||||
|
// we only use 48x48 pixel images. Resize as necessary
|
||||||
|
int width = imageImmediate.getWidth(null);
|
||||||
|
int height = imageImmediate.getHeight(null);
|
||||||
|
|
||||||
|
BufferedImage bufferedImage;
|
||||||
|
|
||||||
|
// resize the image, keep aspect ratio
|
||||||
|
if (width > height) {
|
||||||
|
bufferedImage = ImageUtil.resizeImage(image, getImageSize(), -1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bufferedImage = ImageUtil.resizeImage(image, -1, getImageSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
imageCache.put(imageName, new SoftReference<ImageIcon>(new ImageIcon(bufferedImage)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static
|
private static
|
||||||
BufferedImage getImage(String imageName) {
|
ImageIcon getImage(String imageName) {
|
||||||
BufferedImage bufferedImage = imageCache.get(imageName);
|
ImageIcon image = null;
|
||||||
InputStream resourceAsStream = null;
|
InputStream resourceAsStream = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (bufferedImage == null) {
|
SoftReference<ImageIcon> reference = imageCache.get(imageName);
|
||||||
|
|
||||||
|
if (reference != null) {
|
||||||
|
image = reference.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (image == null) {
|
||||||
String name = IMAGE_PATH + File.separatorChar + imageName;
|
String name = IMAGE_PATH + File.separatorChar + imageName;
|
||||||
|
|
||||||
resourceAsStream = LocationResolver.getResourceAsStream(name);
|
resourceAsStream = LocationResolver.getResourceAsStream(name);
|
||||||
|
|
||||||
bufferedImage = ImageIO.read(resourceAsStream);
|
image = new ImageIcon(ImageUtil.getImageImmediate(ImageIO.read(resourceAsStream)));
|
||||||
imageCache.put(imageName, bufferedImage);
|
imageCache.put(imageName, new SoftReference<ImageIcon>(image));
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -143,7 +181,7 @@ class Notify {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bufferedImage;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -158,7 +196,7 @@ class Notify {
|
||||||
boolean hideCloseButton;
|
boolean hideCloseButton;
|
||||||
boolean isDark = false;
|
boolean isDark = false;
|
||||||
int screenNumber = Short.MIN_VALUE;
|
int screenNumber = Short.MIN_VALUE;
|
||||||
private Image graphic;
|
private ImageIcon icon;
|
||||||
|
|
||||||
ActionHandler<Notify> onCloseAction;
|
ActionHandler<Notify> onCloseAction;
|
||||||
private INotify notifyPopup;
|
private INotify notifyPopup;
|
||||||
|
@ -191,11 +229,24 @@ class Notify {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies the graphic
|
* Specifies the image
|
||||||
*/
|
*/
|
||||||
public
|
public
|
||||||
Notify graphic(Image graphic) {
|
Notify image(Image image) {
|
||||||
this.graphic = graphic;
|
// we only use 48x48 pixel images. Resize as necessary
|
||||||
|
int width = image.getWidth(null);
|
||||||
|
int height = image.getHeight(null);
|
||||||
|
|
||||||
|
BufferedImage bufferedImage = ImageUtil.getBufferedImage(image);
|
||||||
|
|
||||||
|
// resize the image, keep aspect ratio
|
||||||
|
if (width > height) {
|
||||||
|
bufferedImage = ImageUtil.resizeImage(bufferedImage, 48, -1);
|
||||||
|
} else {
|
||||||
|
bufferedImage = ImageUtil.resizeImage(bufferedImage, -1, 48);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.icon = new ImageIcon(bufferedImage);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,47 +310,48 @@ class Notify {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows the notification with the built-in 'warning' graphic.
|
* Shows the notification with the built-in 'warning' image.
|
||||||
*/
|
*/
|
||||||
public
|
public
|
||||||
void showWarning() {
|
void showWarning() {
|
||||||
name = "dialog-warning.png";
|
name = DIALOG_WARNING;
|
||||||
graphic(getImage(name));
|
icon = getImage(name);
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows the notification with the built-in 'information' graphic.
|
* Shows the notification with the built-in 'information' image.
|
||||||
*/
|
*/
|
||||||
public
|
public
|
||||||
void showInformation() {
|
void showInformation() {
|
||||||
name = "dialog-information.png";
|
name = DIALOG_INFORMATION;
|
||||||
graphic(getImage(name));
|
icon = getImage(name);
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows the notification with the built-in 'error' graphic.
|
* Shows the notification with the built-in 'error' image.
|
||||||
*/
|
*/
|
||||||
public
|
public
|
||||||
void showError() {
|
void showError() {
|
||||||
name = "dialog-error.png";
|
name = DIALOG_ERROR;
|
||||||
graphic(getImage(name));
|
icon = getImage(name);
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows the notification with the built-in 'confirm' graphic.
|
* Shows the notification with the built-in 'confirm' image.
|
||||||
*/
|
*/
|
||||||
public
|
public
|
||||||
void showConfirm() {
|
void showConfirm() {
|
||||||
name = "dialog-confirm.png";
|
name = DIALOG_CONFIRM;
|
||||||
graphic(getImage(name));
|
icon = getImage(name);
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows the notification. If the Notification is assigned to a screen, but shown in a JFrame, the screen number will be ignored.
|
* Shows the notification. If the Notification is assigned to a screen, but shown inside a Swing/etc parent, the screen number will be
|
||||||
|
* ignored.
|
||||||
*/
|
*/
|
||||||
public
|
public
|
||||||
void show() {
|
void show() {
|
||||||
|
@ -310,26 +362,7 @@ class Notify {
|
||||||
public
|
public
|
||||||
void run() {
|
void run() {
|
||||||
final Notify notify = Notify.this;
|
final Notify notify = Notify.this;
|
||||||
final Image graphic = notify.graphic;
|
final ImageIcon image = notify.icon;
|
||||||
|
|
||||||
// we ONLY cache our own icons
|
|
||||||
ImageIcon imageIcon = null;
|
|
||||||
if (graphic != null) {
|
|
||||||
if (name != null) {
|
|
||||||
imageIcon = imageIconCache.get(name);
|
|
||||||
if (imageIcon == null) {
|
|
||||||
Image image = new ImageIcon(graphic).getImage();
|
|
||||||
|
|
||||||
// have to do this twice, so that it will finish loading the image (weird callback stuff is required if we don't do this)
|
|
||||||
imageIcon = new ImageIcon(image);
|
|
||||||
|
|
||||||
imageIconCache.put(name, imageIcon);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
imageIcon = new ImageIcon(graphic);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Theme theme;
|
Theme theme;
|
||||||
if (notify.theme != null) {
|
if (notify.theme != null) {
|
||||||
|
@ -340,9 +373,9 @@ class Notify {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window == null) {
|
if (window == null) {
|
||||||
notifyPopup = new AsFrame(notify, graphic, imageIcon, theme);
|
notifyPopup = new AsFrame(notify, image, theme);
|
||||||
} else {
|
} else {
|
||||||
notifyPopup = new AsDialog(notify, graphic, imageIcon, window, theme);
|
notifyPopup = new AsDialog(notify, image, window, theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyPopup.setVisible(true);
|
notifyPopup.setVisible(true);
|
||||||
|
@ -354,7 +387,7 @@ class Notify {
|
||||||
});
|
});
|
||||||
|
|
||||||
// don't need to hang onto these.
|
// don't need to hang onto these.
|
||||||
graphic = null;
|
icon = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -126,7 +126,7 @@ class NotifyTest {
|
||||||
.hideAfter(13000)
|
.hideAfter(13000)
|
||||||
.position(Pos.BOTTOM_LEFT)
|
.position(Pos.BOTTOM_LEFT)
|
||||||
// .setScreen(0)
|
// .setScreen(0)
|
||||||
.darkStyle()
|
// .darkStyle()
|
||||||
// .shake(1300, 4)
|
// .shake(1300, 4)
|
||||||
// .shake(1300, 10)
|
// .shake(1300, 10)
|
||||||
.hideCloseButton()
|
.hideCloseButton()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user