/* * Copyright PMEase (c) 2005 - 2010, * Date: Jan 13, 2010 10:41:01 PM * * All rights reserved. * * Revision: $Id$ */ package com.pmease.quickbuild.monitor.notifier; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.pmease.quickbuild.monitor.cache.ColorCache; import com.pmease.quickbuild.monitor.cache.FontCache; import com.pmease.quickbuild.monitor.cache.ImageCache; import com.pmease.quickbuild.monitor.gui.TrayMonitor; import com.pmease.quickbuild.monitor.resource.Resource; import com.pmease.quickbuild.monitor.utils.SWTUtils; public class Notifier { private static final Logger logger = LoggerFactory.getLogger(Notifier.class); // how long each tick is when fading in (in ms) private final int FADE_TIMER = 50; // how long each tick is when fading out (in ms) private final int FADE_IN_STEP = 30; // how many tick steps we use when fading out private final int FADE_OUT_STEP = 8; // how high the alpha value is when we have finished fading in private final int FINAL_ALPHA = 225; // title foreground color private Color titleFgColor = ColorCache.getColor(40, 73, 97); // text foreground color private Color fgColor = titleFgColor; // shell gradient background color - top private Color bgFgGradient = ColorCache.getColor(51, 51, 51); // shell gradient background color - bottom private Color bgBgGradient = ColorCache.getColor(00, 00, 00); // shell border color private Color borderColor = ColorCache.getColor(40, 73, 97); // image used when drawing private Image oldImage; private Shell shell; public final TrayMonitor monitor; private final String title; private final String message; public enum NotificationType { SUCCESS, WARNING, ERROR, FATAL } private final NotificationType notificationType; private WavePlayer player = null; private int index; public Notifier(TrayMonitor trayMonitor, String title, String message, NotificationType notificationType) { this.monitor = trayMonitor; this.title = title; this.message = message; this.notificationType = notificationType; try { this.player = new WavePlayer(); } catch (NoClassDefFoundError e) { // ignore this.player = null; } } private void createShell() { shell = new Shell(monitor.getShell(), SWT.NO_FOCUS | SWT.ON_TOP | SWT.NO_TRIM); shell.setLayout(new FillLayout()); shell.setForeground(fgColor); shell.setBackgroundMode(SWT.INHERIT_DEFAULT); shell.addListener(SWT.Resize, new Listener() { public void handleEvent(Event e) { try { // get the size of the drawing area Rectangle rect = shell.getClientArea(); // create a new image with that size Image newImage = new Image(Display.getDefault(), Math.max(1, rect.width), rect.height); // create a GC object we can use to draw with GC gc = new GC(newImage); // fill background gc.setForeground(bgFgGradient); gc.setBackground(bgBgGradient); gc.fillGradientRectangle(rect.x, rect.y, rect.width, rect.height, true); // draw shell edge gc.setLineWidth(2); gc.setForeground(borderColor); gc.drawRectangle(rect.x + 1, rect.y + 1, rect.width - 2, rect.height - 2); // remember to dipose the GC object! gc.dispose(); // now set the background image on the shell shell.setBackgroundImage(newImage); // remember/dispose old used iamge if (oldImage != null) { oldImage.dispose(); } oldImage = newImage; } catch (Exception err) { err.printStackTrace(); } } }); final Composite inner = new Composite(shell, SWT.NONE); GridLayout gl = new GridLayout(2, false); gl.marginLeft = 5; gl.marginTop = 0; gl.marginRight = 5; gl.marginBottom = 5; gl.numColumns = 3; inner.setLayout(gl); createContents(inner); if (monitor.getShell() == null || monitor.getShell().getMonitor() == null) { return; } monitor.windowManager.addNotifier(this); shell.setAlpha(0); shell.setVisible(true); } protected Composite createContents(Composite inner) { createTitleComponent(inner); createMessageComponent(inner); return inner; } protected Control createTitleComponent(Composite inner) { CLabel imgLabel = new CLabel(inner, SWT.NONE); // imgLabel.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.HORIZONTAL_ALIGN_BEGINNING)); // GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).span(1, 2).applyTo(imgLabel); imgLabel.setImage(ImageCache.getImage(notificationType.name().toLowerCase() + ".png")); GridData data = new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.HORIZONTAL_ALIGN_BEGINNING); data.verticalSpan = 2; data.horizontalSpan = 1; imgLabel.setLayoutData(data); CLabel titleLabel = new CLabel(inner, SWT.NONE); // titleLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_CENTER)); // GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).applyTo(titleLabel); titleLabel.setText(title); Font f = titleLabel.getFont(); FontData fd = f.getFontData()[0]; fd.setStyle(SWT.BOLD); fd.height = 12; titleLabel.setFont(FontCache.getFont(fd)); titleLabel.setForeground(ColorCache.getColor(255, 255, 255)); data = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_CENTER); data.horizontalSpan = 1; titleLabel.setLayoutData(data); CLabel closeLabel = new CLabel(inner, SWT.NONE); closeLabel.setImage(ImageCache.getImage("close.png")); data = new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.HORIZONTAL_ALIGN_BEGINNING); data.horizontalSpan = 1; closeLabel.setLayoutData(data); closeLabel.addMouseListener(new MouseAdapter() { @Override public void mouseUp(MouseEvent e) { Notifier.this.close(); } }); return titleLabel; } protected Control createMessageComponent(Composite inner) { try { Label messageLabel = new Label(inner, getLabelStyle()); Font tf = messageLabel.getFont(); FontData tfd = tf.getFontData()[0]; tfd.setStyle(SWT.BOLD); tfd.height = 11; messageLabel.setFont(FontCache.getFont(tfd)); GridData gd = new GridData(GridData.FILL_BOTH); gd.horizontalSpan = 2; messageLabel.setLayoutData(gd); messageLabel.setText(message); messageLabel.setForeground(ColorCache.getColor(195, 195, 195)); return messageLabel; } catch (Exception e) { logger.error("createMessageComponent failed!", e); throw new RuntimeException(e); } } protected int getLabelStyle() { return SWT.WRAP; } public void open() { try { if (shell == null || shell.isDisposed()) { createShell(); } Boolean playSound = Boolean.valueOf(monitor.settings.getProperty("playSound", "true")); if (playSound && player != null) { if (notificationType == NotificationType.SUCCESS) { player.play(Resource.getStream("good.wav")); } else { player.play(Resource.getStream("bad.wav")); } } fadeIn(shell); } catch (Exception e) { throw new RuntimeException(e); } } private void fadeIn(final Shell shell) { Runnable run = new Runnable() { public void run() { try { if (shell == null || shell.isDisposed()) { return; } int cur = shell.getAlpha(); if (SWTUtils.hasAlphaSupport()) { cur += FADE_IN_STEP; if (cur > FINAL_ALPHA) { cur = FINAL_ALPHA; startTimer(shell); return; } shell.setAlpha(cur); shell.getDisplay().timerExec(FADE_TIMER, this); } else { shell.setAlpha(FINAL_ALPHA); startTimer(shell); return; } } catch (Exception e) { logger.error("Exception occurred!", e); } } }; shell.getDisplay().timerExec(FADE_TIMER, run); } private void startTimer(final Shell shell) { Runnable run = new Runnable() { public void run() { try { if (shell == null || shell.isDisposed()) { return; } if (SWTUtils.hasAlphaSupport()) { fadeOut(shell); } else { close(); } } catch (Exception e) { logger.error("Exception occurred!", e); } } }; shell.getDisplay().timerExec(monitor.settings.getNotificationDisplayTime() * 1000, run); } private void fadeOut(final Shell shell) { final Runnable run = new Runnable() { public void run() { try { if (shell == null || shell.isDisposed()) { return; } int cur = shell.getAlpha(); cur -= FADE_OUT_STEP; if (cur <= 0) { close(); return; } shell.setAlpha(cur); shell.getDisplay().timerExec(FADE_TIMER, this); } catch (Exception e) { logger.error("Exception occurred!", e); } } }; shell.getDisplay().timerExec(FADE_TIMER, run); } public void close() { shell.setAlpha(0); if (oldImage != null) { oldImage.dispose(); } if (player != null) { player.close(); } shell.dispose(); monitor.windowManager.removeNotifier(this); } public String getTitle() { return title; } public String getMessage() { return message; } public NotificationType getNotificationType() { return notificationType; } public int getIndex() { return index; } public void setIndex(int index) { this.index = index; } public Shell getShell() { return shell; } }