package btdex.ui; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.geom.RoundRectangle2D; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.Timer; public class Toast extends JDialog { private static final long serialVersionUID = -1602907470843951525L; public enum Style { NORMAL, SUCCESS, ERROR }; public static final int LENGTH_SHORT = 5000; public static final int LENGTH_LONG = 10000; public static final Color ERROR_RED = new Color(121, 0, 0); public static final Color SUCCESS_GREEN = new Color(22, 127, 57); public static final Color NORMAL_BLACK = new Color(0, 0, 0); private final float MAX_OPACITY = 0.8f; private final float OPACITY_INCREMENT = 0.05f; private final int FADE_REFRESH_RATE = 20; private final int WINDOW_RADIUS = 15; private final int DISTANCE_FROM_PARENT_TOP = 35; private JFrame mOwner; private String mText; private int mDuration; private Color mBackgroundColor = Color.BLACK; private Color mForegroundColor = Color.WHITE; private Point mLocation; private boolean opacitySupported = true; public Toast(JFrame owner){ super(owner); mOwner = owner; } private void createGUI(){ addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent e) { setShape(new RoundRectangle2D.Double(0, 0, getWidth(), getHeight(), WINDOW_RADIUS, WINDOW_RADIUS)); } }); setAlwaysOnTop(true); setUndecorated(true); setFocusableWindowState(false); setModalityType(ModalityType.MODELESS); getContentPane().setBackground(mBackgroundColor); JLabel label = new JLabel(mText); label.setFont(label.getFont().deriveFont(16.0f)); label.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); label.setForeground(mForegroundColor); add(label); pack(); } public void fadeIn() { final Timer timer = new Timer(FADE_REFRESH_RATE, null); timer.setRepeats(true); timer.addActionListener(new ActionListener() { private float opacity = 0; @Override public void actionPerformed(ActionEvent e) { opacity += OPACITY_INCREMENT; if(opacitySupported) setOpacity(Math.min(opacity, MAX_OPACITY)); if (opacity >= MAX_OPACITY){ timer.stop(); } } }); try { setOpacity(0); } catch (UnsupportedOperationException e) { // translucency not supported on some systems opacitySupported = false; } timer.start(); Point loc = new Point(getToastLocation()); setLocation(loc); setVisible(true); } public void fadeOut() { final Timer timer = new Timer(FADE_REFRESH_RATE, null); timer.setRepeats(true); timer.addActionListener(new ActionListener() { private float opacity = MAX_OPACITY; @Override public void actionPerformed(ActionEvent e) { opacity -= OPACITY_INCREMENT; if(opacitySupported) setOpacity(Math.max(opacity, 0)); if (opacity <= 0) { timer.stop(); setVisible(false); dispose(); } } }); if(opacitySupported) setOpacity(MAX_OPACITY); timer.start(); } private Point getToastLocation(){ if(mLocation!=null) { Point p = new Point(mLocation); p.x -= getWidth()/2; p.y -= getHeight(); return p; } Point ownerLoc = mOwner.getLocation(); int x = (int) (ownerLoc.getX() + ((mOwner.getWidth() - this.getWidth()) / 2)); int y = (int) (ownerLoc.getY() + mOwner.getHeight()*DISTANCE_FROM_PARENT_TOP/100); return new Point(x, y); } public void setText(String text){ mText = text; } public void setDuration(int duration){ mDuration = duration; } @Override public void setBackground(Color backgroundColor){ mBackgroundColor = backgroundColor; } @Override public void setForeground(Color foregroundColor){ mForegroundColor = foregroundColor; } public static Toast makeText(JFrame owner, String text){ return makeText(owner, text, LENGTH_SHORT); } public static Toast makeText(JFrame owner, String text, Style style){ return makeText(owner, text, LENGTH_SHORT, style); } public static Toast makeText(JFrame owner, String text, int duration){ return makeText(owner, text, duration, Style.NORMAL); } public static Toast makeText(JFrame owner, String text, int duration, Style style){ Toast toast = new Toast(owner); toast.mText = text; toast.mDuration = duration; if (style == Style.SUCCESS) toast.mBackgroundColor = SUCCESS_GREEN; if (style == Style.ERROR) toast.mBackgroundColor = ERROR_RED; if (style == Style.NORMAL) toast.mBackgroundColor = NORMAL_BLACK; return toast; } public void display(Component c) { Point p = c.getLocationOnScreen(); p.x += c.getWidth()/2; mLocation = p; display(); } public void display(){ new Thread(new Runnable() { @Override public void run() { try{ createGUI(); fadeIn(); Thread.sleep(mDuration); fadeOut(); } catch(Exception ex){ ex.printStackTrace(); } } }).start(); } public static void main(String []args){ final JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.setSize(new Dimension(500, 300)); JButton b = new JButton("Toast!"); b.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { Toast.makeText(frame, "Annotations were successfully saved.", Style.SUCCESS).display(); } }); frame.add(b); frame.setVisible(true); } }