diff --git a/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/identity/event/IRosterChangeEvent.java b/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/identity/event/IRosterChangeEvent.java index 0565b546c4..3356ea0976 100644 --- a/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/identity/event/IRosterChangeEvent.java +++ b/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/identity/event/IRosterChangeEvent.java @@ -20,6 +20,7 @@ package com.raytheon.uf.viz.collaboration.comm.identity.event; import org.jivesoftware.smack.RosterEntry; +import org.jivesoftware.smack.packet.Presence; /** * Event fired when the roster has changed @@ -30,7 +31,8 @@ import org.jivesoftware.smack.RosterEntry; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Apr 6, 2012 jkorman Initial creation + * Apr 06, 2012 jkorman Initial creation. + * Feb 24, 2014 2632 mpduff Added getPresence, changed getItem to getEntry. * * * @@ -43,15 +45,22 @@ public interface IRosterChangeEvent { /** * Get the event type. * - * @return The event type. + * @return The event type */ - public RosterChangeType getType(); + RosterChangeType getType(); /** - * Get the changed entry + * Get the changed entry. * - * @return The changed entry. + * @return The changed entry */ - public RosterEntry getItem(); + RosterEntry getEntry(); + + /** + * Get the Presence object. + * + * @return The Presence object + */ + Presence getPresence(); } diff --git a/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/provider/event/RosterChangeEvent.java b/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/provider/event/RosterChangeEvent.java index c538af093d..0e99c81091 100644 --- a/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/provider/event/RosterChangeEvent.java +++ b/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/provider/event/RosterChangeEvent.java @@ -20,6 +20,7 @@ package com.raytheon.uf.viz.collaboration.comm.provider.event; import org.jivesoftware.smack.RosterEntry; +import org.jivesoftware.smack.packet.Presence; import com.raytheon.uf.viz.collaboration.comm.identity.event.IRosterChangeEvent; import com.raytheon.uf.viz.collaboration.comm.identity.event.RosterChangeType; @@ -34,6 +35,7 @@ import com.raytheon.uf.viz.collaboration.comm.identity.event.RosterChangeType; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Apr 11, 2012 jkorman Initial creation + * Feb 24, 2014 2632 mpduff Added getPresence, changed getItem to getEntry. * * * @@ -45,7 +47,10 @@ public class RosterChangeEvent implements IRosterChangeEvent { private final RosterChangeType type; - private final RosterEntry item; + private final RosterEntry entry; + + /** The presence object */ + private Presence presence; /** * Create an instance of this event using the given type and entry. @@ -55,9 +60,28 @@ public class RosterChangeEvent implements IRosterChangeEvent { * @param entry * The changed entry. */ - public RosterChangeEvent(RosterChangeType type, RosterEntry item) { + public RosterChangeEvent(RosterChangeType type, RosterEntry entry) { this.type = type; - this.item = item; + this.entry = entry; + } + + /** + * Create an instance of this event using the given type, entry, and + * presence. + * + * @param type + * The event type. + * @param entry + * The changed entry. + * @param presence + * The presence object + */ + public RosterChangeEvent(RosterChangeType type, RosterEntry entry, + Presence presence) { + this.type = type; + this.entry = entry; + this.presence = presence; + } /** @@ -78,8 +102,24 @@ public class RosterChangeEvent implements IRosterChangeEvent { * @see com.raytheon.uf.viz.collaboration.comm.identity.event.IRosterChangeEvent#getEntry() */ @Override - public RosterEntry getItem() { - return item; + public RosterEntry getEntry() { + return entry; + } + + /** + * @return the presence + */ + @Override + public Presence getPresence() { + return presence; + } + + /** + * @param presence + * the presence to set + */ + public void setPresence(Presence presence) { + this.presence = presence; } } diff --git a/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/provider/session/CollaborationConnection.java b/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/provider/session/CollaborationConnection.java index 4a1417236b..f92bbd4987 100644 --- a/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/provider/session/CollaborationConnection.java +++ b/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/provider/session/CollaborationConnection.java @@ -113,6 +113,7 @@ import com.raytheon.uf.viz.collaboration.comm.provider.user.VenueParticipant; * Feb 3, 2014 2699 bclement removed unneeded catch in joinTextOnlyVenue * Feb 13, 2014 2751 bclement better types for venueid and invitor * Feb 18, 2014 2793 bclement improved disconnection notification and handling + * Feb 24, 2014 2632 mpduff Fix roster change type for presence change. * * * @@ -136,9 +137,9 @@ public class CollaborationConnection implements IEventPublisher { private static Map instanceMap = new HashMap(); - private Map sessions; + private final Map sessions; - private UserId user; + private final UserId user; private Presence userPresence; @@ -146,11 +147,11 @@ public class CollaborationConnection implements IEventPublisher { private IAccountManager accountManager = null; - private EventBus eventBus; + private final EventBus eventBus; - private ContactsManager contactsMgr; + private final ContactsManager contactsMgr; - private CollaborationConnectionData connectionData; + private final CollaborationConnectionData connectionData; private XMPPConnection connection; @@ -195,7 +196,7 @@ public class CollaborationConnection implements IEventPublisher { conConfig.setCompressionEnabled(COMPRESS); connection = new XMPPConnection(conConfig); - + connectInternal(connectionData.getUserName(), password); this.user = new UserId(connectionData.getUserName(), @@ -423,12 +424,12 @@ public class CollaborationConnection implements IEventPublisher { */ public IVenueSession joinTextOnlyVenue(String venueName, String handle) throws CollaborationException { - VenueSession session = new VenueSession(eventBus, this); - session.configureVenue(venueName, handle); - session.connectToRoom(); - sessions.put(session.getSessionId(), session); - postEvent(session); - return session; + VenueSession session = new VenueSession(eventBus, this); + session.configureVenue(venueName, handle); + session.connectToRoom(); + sessions.put(session.getSessionId(), session); + postEvent(session); + return session; } /** @@ -482,33 +483,32 @@ public class CollaborationConnection implements IEventPublisher { private void setupInternalConnectionListeners() { final Roster roster = connection.getRoster(); roster.addRosterListener(new RosterListener() { - + @Override public void presenceChanged(Presence presence) { String fromId = presence.getFrom(); if (contactsMgr != null) { UserId u = IDConverter.convertFrom(fromId); if (u != null) { - RosterEntry entry = contactsMgr - .getRosterEntry(u); + RosterEntry entry = contactsMgr.getRosterEntry(u); eventBus.post(entry); IRosterChangeEvent event = new RosterChangeEvent( - RosterChangeType.MODIFY, entry); + RosterChangeType.PRESENCE, entry, presence); eventBus.post(event); } } } - + @Override public void entriesUpdated(Collection addresses) { send(addresses, RosterChangeType.MODIFY); } - + @Override public void entriesDeleted(Collection addresses) { send(addresses, RosterChangeType.DELETE); } - + @Override public void entriesAdded(Collection addresses) { send(addresses, RosterChangeType.ADD); @@ -546,16 +546,17 @@ public class CollaborationConnection implements IEventPublisher { } } - private void setupConnectionListener(){ - if (isConnected()){ + private void setupConnectionListener() { + if (isConnected()) { connection.addConnectionListener(new ConnectionListener() { - + @Override public void reconnectionSuccessful() { - statusHandler.debug("Client successfully reconnected to server"); + statusHandler + .debug("Client successfully reconnected to server"); postSystemMessageToVenues("Connection to collaboration server reestablished."); } - + @Override public void reconnectionFailed(Exception e) { String reason = getErrorReason(e); @@ -563,12 +564,13 @@ public class CollaborationConnection implements IEventPublisher { + reason, e); sendDisconnectNotice(reason); } - + @Override public void reconnectingIn(int seconds) { - statusHandler.debug("Client reconnecting to server in " + seconds + " seconds" ); + statusHandler.debug("Client reconnecting to server in " + + seconds + " seconds"); } - + @Override public void connectionClosedOnError(Exception e) { String reason = getErrorReason(e); @@ -591,7 +593,7 @@ public class CollaborationConnection implements IEventPublisher { } return msg == null ? e.getLocalizedMessage() : msg; } - + @Override public void connectionClosed() { statusHandler.info("Server closed connection"); diff --git a/cave/com.raytheon.uf.viz.collaboration.ui/plugin.xml b/cave/com.raytheon.uf.viz.collaboration.ui/plugin.xml index 9c39ea0025..f7f3f6bfed 100644 --- a/cave/com.raytheon.uf.viz.collaboration.ui/plugin.xml +++ b/cave/com.raytheon.uf.viz.collaboration.ui/plugin.xml @@ -163,6 +163,11 @@ id="com.raytheon.uf.viz.collaboration.ui.prefs.collaborationroomchangepreferencepage" name="Room Alerts" category="com.raytheon.uf.viz.collaboration.ui.prefs.collaborationpreferencepage"/> + diff --git a/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/CollaborationGroupView.java b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/CollaborationGroupView.java index 2fd5361e09..d514c5f736 100644 --- a/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/CollaborationGroupView.java +++ b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/CollaborationGroupView.java @@ -92,6 +92,7 @@ import com.raytheon.uf.viz.collaboration.comm.provider.user.ContactsManager.Grou import com.raytheon.uf.viz.collaboration.comm.provider.user.IDConverter; import com.raytheon.uf.viz.collaboration.comm.provider.user.SharedGroup; import com.raytheon.uf.viz.collaboration.comm.provider.user.UserId; +import com.raytheon.uf.viz.collaboration.ui.actions.AddNotifierAction; import com.raytheon.uf.viz.collaboration.ui.actions.AddToGroupAction; import com.raytheon.uf.viz.collaboration.ui.actions.ArchiveViewerAction; import com.raytheon.uf.viz.collaboration.ui.actions.ChangeFontAction; @@ -116,6 +117,7 @@ import com.raytheon.uf.viz.collaboration.ui.actions.UserSearchAction; import com.raytheon.uf.viz.collaboration.ui.data.AlertWordWrapper; import com.raytheon.uf.viz.collaboration.ui.data.CollaborationGroupContainer; import com.raytheon.uf.viz.collaboration.ui.data.SessionGroupContainer; +import com.raytheon.uf.viz.collaboration.ui.notifier.NotifierTools; import com.raytheon.uf.viz.collaboration.ui.session.AbstractSessionView; import com.raytheon.uf.viz.core.VizApp; import com.raytheon.uf.viz.core.icon.IconUtil; @@ -142,6 +144,7 @@ import com.raytheon.viz.ui.views.CaveFloatingView; * Jan 30, 2014 2698 bclement fixed alias not working for roster entries * removed unneeded subscription for nickname changed events * Feb 12, 2014 2799 bclement fixed double click chat not working for roster entries + * Feb 24, 2014 2632 mpduff Add Notifier actions. * * * @@ -272,6 +275,7 @@ public class CollaborationGroupView extends CaveFloatingView implements }; collapseAllAction = new Action("Collapse All") { + @Override public void run() { if (usersTreeViewer != null) { usersTreeViewer.collapseAll(); @@ -413,6 +417,7 @@ public class CollaborationGroupView extends CaveFloatingView implements if (ContactsManager.isBlocked(entry)) { manager.add(new SendSubReqAction(entry)); } + manager.add(new AddNotifierAction(this)); } else if (o instanceof UserId) { // the user UserId user = (UserId) o; @@ -516,6 +521,7 @@ public class CollaborationGroupView extends CaveFloatingView implements SWT.COLOR_BLACK)); final Text modText = new Text(composite, SWT.NONE); composite.addListener(SWT.Resize, new Listener() { + @Override public void handleEvent(Event e) { Rectangle rect = composite.getClientArea(); modText.setBounds(rect.x + 1, rect.y + 1, rect.width - 2, @@ -523,6 +529,7 @@ public class CollaborationGroupView extends CaveFloatingView implements } }); Listener textListener = new Listener() { + @Override public void handleEvent(final Event e) { switch (e.type) { case SWT.KeyUp: @@ -631,11 +638,13 @@ public class CollaborationGroupView extends CaveFloatingView implements clearButton.addMouseListener(new MouseAdapter() { private MouseMoveListener fMoveListener; + @Override public void mouseDown(MouseEvent e) { clearButton.setImage(pressedImage); fMoveListener = new MouseMoveListener() { private boolean fMouseInButton = true; + @Override public void mouseMove(MouseEvent e) { boolean mouseInButton = isMouseInButton(e); if (mouseInButton != fMouseInButton) { @@ -648,6 +657,7 @@ public class CollaborationGroupView extends CaveFloatingView implements clearButton.addMouseMoveListener(fMoveListener); } + @Override public void mouseUp(MouseEvent e) { if (fMoveListener != null) { clearButton.removeMouseMoveListener(fMoveListener); @@ -670,15 +680,18 @@ public class CollaborationGroupView extends CaveFloatingView implements } }); clearButton.addMouseTrackListener(new MouseTrackAdapter() { + @Override public void mouseEnter(MouseEvent e) { clearButton.setImage(activeImage); } + @Override public void mouseExit(MouseEvent e) { clearButton.setImage(inactiveImage); } }); clearButton.addDisposeListener(new DisposeListener() { + @Override public void widgetDisposed(DisposeEvent e) { inactiveImage.dispose(); activeImage.dispose(); @@ -687,12 +700,14 @@ public class CollaborationGroupView extends CaveFloatingView implements }); clearButton.getAccessible().addAccessibleListener( new AccessibleAdapter() { + @Override public void getName(AccessibleEvent e) { e.result = WorkbenchMessages.FilteredTree_AccessibleListenerClearButton; } }); clearButton.getAccessible().addAccessibleControlListener( new AccessibleControlAdapter() { + @Override public void getRole(AccessibleControlEvent e) { e.detail = ACC.ROLE_PUSHBUTTON; } @@ -767,6 +782,7 @@ public class CollaborationGroupView extends CaveFloatingView implements * * @return */ + @Override public UserId[] getSelectedUsers() { Set selectedUsers = new HashSet(); IStructuredSelection selection = (IStructuredSelection) usersTreeViewer @@ -853,6 +869,8 @@ public class CollaborationGroupView extends CaveFloatingView implements // Refresh the whole tree since there can be instances of the same user // elsewhere that might not .equals this one. refreshUsersTreeViewerAsync(usersTreeViewer.getInput()); + NotifierTools.processNotifiers(rosterChangeEvent.getPresence()); + } @Subscribe diff --git a/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/CollaborationUtils.java b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/CollaborationUtils.java index 6f42d7180f..9e58eef5a5 100644 --- a/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/CollaborationUtils.java +++ b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/CollaborationUtils.java @@ -68,7 +68,7 @@ import com.raytheon.uf.viz.core.icon.IconUtil; public class CollaborationUtils { - private static final transient IUFStatusHandler statusHandler = UFStatus + private static final IUFStatusHandler statusHandler = UFStatus .getHandler(CollaborationUtils.class); public static final Presence.Mode[] statusModes = { Mode.available, @@ -106,7 +106,7 @@ public class CollaborationUtils { "collaboration" + File.separator + "collaborationAliases.xml"); if (file.exists()) { - UserIdWrapper ids = (UserIdWrapper) JAXB.unmarshal(file.getFile(), + UserIdWrapper ids = JAXB.unmarshal(file.getFile(), UserIdWrapper.class); if (ids.getUserIds() == null) { return new UserId[0]; @@ -159,20 +159,21 @@ public class CollaborationUtils { file = PathManagerFactory.getPathManager().getLocalizationFile(context, "collaboration" + File.separator + "alertWords.xml"); if (file.exists() || file.getFile().exists()) { - AlertWordWrapper words = (AlertWordWrapper) JAXB.unmarshal( - file.getFile(), AlertWordWrapper.class); + AlertWordWrapper words = JAXB.unmarshal(file.getFile(), + AlertWordWrapper.class); if (words.getAlertWords() == null) { return new ArrayList(); - } else { - List alertWords = new ArrayList(); - for (int i = 0; i < words.getAlertWords().length; i++) { - alertWords.add(words.getAlertWords()[i]); - } - return alertWords; } - } else { - return new ArrayList(); + + List alertWords = new ArrayList(); + for (int i = 0; i < words.getAlertWords().length; i++) { + alertWords.add(words.getAlertWords()[i]); + } + + return alertWords; } + + return new ArrayList(); } public static void saveAlertWords(List words) { @@ -211,5 +212,4 @@ public class CollaborationUtils { "Unable to save alert words to localization", e); } } - } \ No newline at end of file diff --git a/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/actions/AddNotifierAction.java b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/actions/AddNotifierAction.java new file mode 100644 index 0000000000..83488b1a4c --- /dev/null +++ b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/actions/AddNotifierAction.java @@ -0,0 +1,90 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.viz.collaboration.ui.actions; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.widgets.Display; + +import com.raytheon.uf.viz.collaboration.comm.provider.user.UserId; +import com.raytheon.uf.viz.collaboration.ui.Activator; +import com.raytheon.uf.viz.collaboration.ui.IUserSelector; +import com.raytheon.uf.viz.collaboration.ui.session.AddNotifierDlg; +import com.raytheon.uf.viz.core.icon.IconUtil; + +/** + * Launch the AddNotifier dialog. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Feb 20, 2014    2632    mpduff      Initial creation
+ * 
+ * 
+ * + * @author mpduff + * @version 1.0 + */ + +public class AddNotifierAction extends Action { + /** The IUserSelector */ + private final IUserSelector userSelection; + + /** + * Constructor. + * + * @param userSelection + */ + public AddNotifierAction(IUserSelector userSelection) { + super("Add Notifier...", getNotifierImageDescriptor()); + this.userSelection = userSelection; + } + + /** + * {@inheritDoc} + */ + @Override + public void run() { + List userList = new ArrayList(); + for (UserId id : userSelection.getSelectedUsers()) { + userList.add(id.getName()); + } + AddNotifierDlg dlg = new AddNotifierDlg(Display.getCurrent() + .getActiveShell(), + userList.toArray(new String[userList.size()])); + dlg.open(); + } + + /** + * Get the image descriptor. + * + * @return The ImageDescriptor object + */ + public static ImageDescriptor getNotifierImageDescriptor() { + return IconUtil.getImageDescriptor(Activator.getDefault().getBundle(), + "add_correction.gif"); + } +} diff --git a/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/notifier/Notifier.java b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/notifier/Notifier.java new file mode 100644 index 0000000000..b318fa0b8a --- /dev/null +++ b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/notifier/Notifier.java @@ -0,0 +1,64 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.viz.collaboration.ui.notifier; + +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlEnumValue; +import javax.xml.bind.annotation.XmlType; + +import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; + +/** + * Contact Notifier Types. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Feb 20, 2014   2632     mpduff      Initial creation
+ * 
+ * 
+ * + * @author mpduff + * @version 1.0 + */ +@XmlType(name = "notifier") +@XmlEnum +@DynamicSerialize +public enum Notifier { + @XmlEnumValue("sendMessage") + SendMessage("Sends Me A Message"), @XmlEnumValue("signOn") + SignOn("Signs On"), @XmlEnumValue("signOff") + SignOff("Signs Off"), @XmlEnumValue("away") + Away("Becomes Unavailable"), @XmlEnumValue("return") + Returns("Becomes Available"); + + private String description; + + Notifier(String description) { + this.description = description; + } + + public String getDescription() { + return description; + } +} diff --git a/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/notifier/NotifierTask.java b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/notifier/NotifierTask.java new file mode 100644 index 0000000000..59c7ca0896 --- /dev/null +++ b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/notifier/NotifierTask.java @@ -0,0 +1,237 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.viz.collaboration.ui.notifier; + +import java.util.HashSet; +import java.util.Set; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElements; + +import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; + +/** + * Notifier Task. Holds a list of {@link Notifier} actions. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Feb 20, 2014    2632    mpduff      Initial creation
+ * 
+ * 
+ * + * @author mpduff + * @version 1.0 + */ +@XmlAccessorType(XmlAccessType.NONE) +@DynamicSerialize +public class NotifierTask { + + /** Set of Notifiers for this task */ + @XmlElements({ @XmlElement(name = "notifier") }) + private Set notifierList; + + /** User to whom this task applies */ + @XmlElement + private String userName; + + /** Path to the sound file */ + @XmlElement + private String soundFilePath; + + /** Recurring pounce flag */ + @XmlElement + private boolean recurring; + + /** + * Default Constructor. + */ + public NotifierTask() { + notifierList = new HashSet(); + } + + /** + * Create with the provided list of Notifiers. + * + * @param notifiers + * List of notifiers + */ + public NotifierTask(Notifier... notifiers) { + for (Notifier notifier : notifiers) { + notifierList.add(notifier); + } + } + + /** + * Add a notifier. + * + * @param notifier + * The notifier to add + */ + public void addNotifier(Notifier notifier) { + notifierList.add(notifier); + } + + /** + * Get the notifiers. + * + * @return The Set of Notifiers + */ + public Set getNotifiers() { + return notifierList; + } + + /** + * + * @return the userName + */ + public String getUserName() { + return userName; + } + + /** + * @param userName + * the userName to set + */ + public void setUserName(String userName) { + this.userName = userName; + } + + /** + * @return the notifierList + */ + public Set getNotifierList() { + return notifierList; + } + + /** + * @param notifierList + * the notifierList to set + */ + public void setNotifierList(Set notifierList) { + this.notifierList = notifierList; + } + + /** + * @return the soundFilePath + */ + public String getSoundFilePath() { + return soundFilePath; + } + + /** + * @param soundFilePath + * the soundFilePath to set + */ + public void setSoundFilePath(String soundFilePath) { + this.soundFilePath = soundFilePath; + } + + /** + * @return the recurring + */ + public boolean isRecurring() { + return recurring; + } + + /** + * @param recurring + * the recurring to set + */ + public void setRecurring(boolean recurring) { + this.recurring = recurring; + } + + public boolean isSoundValid() { + return soundFilePath != null && soundFilePath.length() > 0; + } + + public boolean containsSendMessage() { + return notifierList.contains(Notifier.SendMessage); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((notifierList == null) ? 0 : notifierList.hashCode()); + result = prime * result + (recurring ? 1231 : 1237); + result = prime * result + + ((soundFilePath == null) ? 0 : soundFilePath.hashCode()); + result = prime * result + + ((userName == null) ? 0 : userName.hashCode()); + return result; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof NotifierTask)) { + return false; + } + NotifierTask other = (NotifierTask) obj; + if (notifierList == null) { + if (other.notifierList != null) { + return false; + } + } else if (!notifierList.equals(other.notifierList)) { + return false; + } + if (recurring != other.recurring) { + return false; + } + if (soundFilePath == null) { + if (other.soundFilePath != null) { + return false; + } + } else if (!soundFilePath.equals(other.soundFilePath)) { + return false; + } + if (userName == null) { + if (other.userName != null) { + return false; + } + } else if (!userName.equals(other.userName)) { + return false; + } + return true; + } +} diff --git a/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/notifier/NotifierTaskXML.java b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/notifier/NotifierTaskXML.java new file mode 100644 index 0000000000..7ce2b7bce2 --- /dev/null +++ b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/notifier/NotifierTaskXML.java @@ -0,0 +1,66 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.viz.collaboration.ui.notifier; + +import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; +import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; + +/** + * XML Wrapper for the {@link NotifierTask}s + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Feb 21, 2014    2632    mpduff      Initial creation
+ * 
+ * 
+ * + * @author mpduff + * @version 1.0 + */ +@DynamicSerialize +public class NotifierTaskXML { + + /** Array of notifier tasks */ + @DynamicSerializeElement + private NotifierTask[] notifierTasks; + + /** + * @return the notifierTasks + */ + public NotifierTask[] getNotifierTasks() { + if (notifierTasks == null) { + notifierTasks = new NotifierTask[0]; + } + + return notifierTasks; + } + + /** + * @param notifierTasks + * the notifierTasks to set + */ + public void setNotifierTasks(NotifierTask[] notifierTasks) { + this.notifierTasks = notifierTasks; + } +} diff --git a/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/notifier/NotifierTools.java b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/notifier/NotifierTools.java new file mode 100644 index 0000000000..48d956292d --- /dev/null +++ b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/notifier/NotifierTools.java @@ -0,0 +1,297 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.viz.collaboration.ui.notifier; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.xml.bind.JAXB; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.MessageBox; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.Presence.Mode; +import org.jivesoftware.smack.packet.Presence.Type; + +import sun.audio.AudioDataStream; + +import com.raytheon.uf.common.localization.IPathManager; +import com.raytheon.uf.common.localization.LocalizationContext; +import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; +import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; +import com.raytheon.uf.common.localization.LocalizationFile; +import com.raytheon.uf.common.localization.PathManagerFactory; +import com.raytheon.uf.common.localization.exception.LocalizationOpFailedException; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.common.util.FileUtil; +import com.raytheon.uf.viz.collaboration.comm.provider.session.CollaborationConnection; +import com.raytheon.uf.viz.collaboration.comm.provider.user.IDConverter; +import com.raytheon.uf.viz.collaboration.comm.provider.user.UserId; +import com.raytheon.uf.viz.core.sounds.SoundUtil; + +/** + * Contact Notifier Utility Class. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Feb 24, 2014   2632     mpduff      Initial creation
+ * 
+ * 
+ * + * @author mpduff + * @version 1.0 + */ + +public class NotifierTools { + private static final IUFStatusHandler statusHandler = UFStatus + .getHandler(NotifierTools.class); + + /** Set of user names of users currently online */ + private static Set usersOnline = new HashSet(); + + /** Contact notifier config file */ + private static final String NOTIFIER_FILE_PATH = "collaboration/contactNotifiers.xml"; + + /** Sound directory in localization */ + private static final String SOUND_DIR = "collaboration/sounds"; + + /** AudioDataStream object */ + private static AudioDataStream ads = null; + + /** The contact notifier localization file */ + private static LocalizationFile taskFile; + + /** + * Process appropriate notifiers for this presence change. + * + * @param presence + * The updated Presence + */ + public static void processNotifiers(Presence presence) { + UserId userId = IDConverter.convertFrom(presence.getFrom()); + NotifierTask task = NotifierTools.getNotifierTask(userId.getName()); + if (task != null && task.getUserName().equals(userId.getName())) { + Presence rosterPresence = CollaborationConnection.getConnection() + .getContactsManager().getPresence(userId); + Mode mode = rosterPresence.getMode(); + Type type = presence.getType(); + Set notifiers = task.getNotifierList(); + + // Sign on/off events + if (!usersOnline.contains(userId.getName()) + && Type.available == type) { + usersOnline.add(userId.getName()); + if (notifiers.contains(Notifier.SignOn)) { + executeNotifierTask(task); + NotifierTools.taskExecuted(task); + return; + } + } else if (usersOnline.contains(userId.getName()) + && (Type.unavailable == type)) { + if (notifiers.contains(Notifier.SignOff)) { + executeNotifierTask(task); + usersOnline.remove(userId.getName()); + NotifierTools.taskExecuted(task); + return; + } + } + + // presence mode change events + for (Notifier n : notifiers) { + if (Notifier.Returns == n && mode == null) { + /* + * Apparently a null mode is the same as available. See + * AbstractUserLabelProvider.getImageName(); + */ + executeNotifierTask(task); + NotifierTools.taskExecuted(task); + break; + } else if (Notifier.Away == n + && (Mode.away == mode || Mode.xa == mode || Mode.dnd == mode)) { + executeNotifierTask(task); + NotifierTools.taskExecuted(task); + break; + } + } + } + } + + /** + * Execute the NotifierTask. + * + * @param task + * The NotifierTask to execute + */ + private static void executeNotifierTask(NotifierTask task) { + if (task.isSoundValid()) { + SoundUtil.playSound(task.getSoundFilePath()); + } + } + + /** + * Save the notifiers. + * + * @param taskList + * List of NotifierTasks + * @return true if saved successfully + */ + public static boolean saveNotifiers(List taskList) { + for (NotifierTask notifier : taskList) { + String soundPath = notifier.getSoundFilePath(); + if (soundPath != null && !soundPath.isEmpty()) { + String path = copySoundFile(soundPath); + // Reset sound file path the localization + notifier.setSoundFilePath(path); + } + } + + NotifierTaskXML wrapper = new NotifierTaskXML(); + wrapper.setNotifierTasks(taskList.toArray(new NotifierTask[0])); + + LocalizationFile file = null; + IPathManager pm = PathManagerFactory.getPathManager(); + LocalizationContext context = pm.getContext( + LocalizationType.CAVE_STATIC, LocalizationLevel.USER); + file = PathManagerFactory.getPathManager().getLocalizationFile(context, + NOTIFIER_FILE_PATH); + JAXB.marshal(wrapper, file.getFile()); + try { + file.save(); + } catch (LocalizationOpFailedException e) { + statusHandler.handle(Priority.PROBLEM, + "Unable to save Contact Notifiers to localization", e); + return false; + } + + return true; + } + + /** + * Get all the configured NotifierTasks. + * + * @return List of NotifierTasks + */ + public static synchronized List getNotifierTasks() { + List taskList = new ArrayList(); + IPathManager pm = PathManagerFactory.getPathManager(); + LocalizationContext context = pm.getContext( + LocalizationType.CAVE_STATIC, LocalizationLevel.USER); + taskFile = PathManagerFactory.getPathManager().getLocalizationFile( + context, NOTIFIER_FILE_PATH); + if (taskFile.exists() || taskFile.getFile().exists()) { + NotifierTaskXML wrapper = JAXB.unmarshal(taskFile.getFile(), + NotifierTaskXML.class); + if (wrapper != null) { + for (NotifierTask task : wrapper.getNotifierTasks()) { + taskList.add(task); + } + } + } + + return taskList; + } + + /** + * Copy the sound file to cave static user level localization. + * + * @param soundPath + * The path to the file to copy + * @return The new path + */ + private static String copySoundFile(String soundPath) { + String[] dirs = soundPath.split(File.separator); + String filename = dirs[dirs.length - 1]; + IPathManager pm = PathManagerFactory.getPathManager(); + LocalizationContext context = pm.getContext( + LocalizationType.CAVE_STATIC, LocalizationLevel.USER); + LocalizationFile lFile = pm.getLocalizationFile(context, + FileUtil.join(SOUND_DIR, filename)); + if (lFile.exists() && !soundPath.equals(lFile.getFile().getPath())) { + MessageBox messageBox = new MessageBox(Display.getCurrent() + .getActiveShell(), SWT.YES | SWT.NO); + messageBox.setText("File exists"); + messageBox + .setMessage("File already exists, overwrite the existing file? "); + int answer = messageBox.open(); + if (answer == SWT.YES) { + return copyFile(soundPath, lFile); + } + } + if (!lFile.exists()) { + return copyFile(soundPath, lFile); + } + + return soundPath; + } + + private static String copyFile(String path, LocalizationFile lFile) { + File soundFile = new File(path); + + File destination = lFile.getFile(); + try { + FileUtil.copyFile(soundFile, destination); + lFile.save(); + } catch (IOException e) { + statusHandler.handle(Priority.PROBLEM, + "Error Occured copying sound file", e); + } catch (LocalizationOpFailedException e) { + statusHandler.handle(Priority.PROBLEM, + "Error Occured copying sound file", e); + } + + return destination.getAbsolutePath(); + } + + /** + * Get a notifier task for the specified user name. + * + * @param name + * The user name + * @return The NotifierTask or null if none + */ + public static NotifierTask getNotifierTask(String name) { + for (NotifierTask task : getNotifierTasks()) { + if (task.getUserName().equals(name)) { + return task; + } + } + + return null; + } + + public static synchronized void taskExecuted(NotifierTask task) { + if (!task.isRecurring()) { + List tasks = getNotifierTasks(); + tasks.remove(task); + saveNotifiers(tasks); + } + } +} diff --git a/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/prefs/CollaborationPreferencesLabelProvider.java b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/prefs/AlertWordLabelProvider.java similarity index 89% rename from cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/prefs/CollaborationPreferencesLabelProvider.java rename to cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/prefs/AlertWordLabelProvider.java index da4440c1e5..3b3872fc96 100644 --- a/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/prefs/CollaborationPreferencesLabelProvider.java +++ b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/prefs/AlertWordLabelProvider.java @@ -32,7 +32,7 @@ import org.eclipse.swt.widgets.Display; import com.raytheon.uf.viz.collaboration.ui.data.AlertWord; /** - * TODO Add Description + * Get the labels for the Alert Words for the preference page. * *
  * 
@@ -40,7 +40,8 @@ import com.raytheon.uf.viz.collaboration.ui.data.AlertWord;
  * 
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
- * May 17, 2012            mnash     Initial creation
+ * May 17, 2012            mnash       Initial creation
+ * Feb 24, 2014   2632     mpduff      Renamed from CollaborationPreferencesLabelProvider
  * 
  * 
* @@ -48,7 +49,7 @@ import com.raytheon.uf.viz.collaboration.ui.data.AlertWord; * @version 1.0 */ -public class CollaborationPreferencesLabelProvider extends ColumnLabelProvider { +public class AlertWordLabelProvider extends ColumnLabelProvider { private List colors = null; @@ -57,7 +58,7 @@ public class CollaborationPreferencesLabelProvider extends ColumnLabelProvider { /** * */ - public CollaborationPreferencesLabelProvider() { + public AlertWordLabelProvider() { colors = new ArrayList(); fonts = new ArrayList(); } diff --git a/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/prefs/CollaborationAlertWordsPreferencePage.java b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/prefs/CollaborationAlertWordsPreferencePage.java index 6dfc3b6817..cdeaca66b8 100644 --- a/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/prefs/CollaborationAlertWordsPreferencePage.java +++ b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/prefs/CollaborationAlertWordsPreferencePage.java @@ -57,7 +57,7 @@ import com.raytheon.uf.viz.collaboration.ui.data.AlertWord; import com.raytheon.uf.viz.collaboration.ui.data.AlertWordWrapper; /** - * TODO Add Description + * The alert words preference page for collaboration. * *
  * 
@@ -65,7 +65,8 @@ import com.raytheon.uf.viz.collaboration.ui.data.AlertWordWrapper;
  * 
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
- * May 17, 2012            mnash     Initial creation
+ * May 17, 2012            mnash       Initial creation
+ * Feb 24, 2014   2632     mpduf       Created CollaborationPreferencesAlertWordLabelProvider
  * 
  * 
* @@ -100,7 +101,7 @@ public class CollaborationAlertWordsPreferencePage extends viewer = new TableViewer(getFieldEditorParent()); viewer.setContentProvider(new CollaborationPreferenceContentProvider()); - viewer.setLabelProvider(new CollaborationPreferencesLabelProvider()); + viewer.setLabelProvider(new AlertWordLabelProvider()); viewer.getTable().setLayoutData(data); final StringFieldEditor stringEditor = new StringFieldEditor( @@ -255,6 +256,7 @@ public class CollaborationAlertWordsPreferencePage extends viewer.setInput(CollaborationUtils.getAlertWords()); } + @Override public boolean performOk() { List words = (List) viewer.getInput(); CollaborationUtils.saveAlertWords(words); diff --git a/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/prefs/ContactNotifierLabelProvider.java b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/prefs/ContactNotifierLabelProvider.java new file mode 100644 index 0000000000..4c73557af1 --- /dev/null +++ b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/prefs/ContactNotifierLabelProvider.java @@ -0,0 +1,51 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.viz.collaboration.ui.prefs; + +import org.eclipse.jface.viewers.ColumnLabelProvider; + +import com.raytheon.uf.viz.collaboration.ui.notifier.NotifierTask; + +/** + * Get the labels for the NotifierTasks for the preference page. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Feb 21, 2014    2632    mpduff      Initial creation
+ * 
+ * 
+ * + * @author mpduff + * @version 1.0 + */ + +public class ContactNotifierLabelProvider extends ColumnLabelProvider { + + @Override + public String getText(Object element) { + NotifierTask task = (NotifierTask) element; + return task.getUserName(); + } + +} diff --git a/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/prefs/ContactNotifierPreferencePage.java b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/prefs/ContactNotifierPreferencePage.java new file mode 100644 index 0000000000..d942d441c0 --- /dev/null +++ b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/prefs/ContactNotifierPreferencePage.java @@ -0,0 +1,283 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.viz.collaboration.ui.prefs; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.jface.preference.PreferencePage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; +import org.jivesoftware.smack.RosterEntry; +import org.jivesoftware.smack.RosterGroup; + +import com.google.common.collect.Lists; +import com.raytheon.uf.viz.collaboration.comm.provider.session.CollaborationConnection; +import com.raytheon.uf.viz.collaboration.comm.provider.user.ContactsManager; +import com.raytheon.uf.viz.collaboration.comm.provider.user.IDConverter; +import com.raytheon.uf.viz.collaboration.comm.provider.user.SharedGroup; +import com.raytheon.uf.viz.collaboration.comm.provider.user.UserId; +import com.raytheon.uf.viz.collaboration.ui.Activator; +import com.raytheon.uf.viz.collaboration.ui.notifier.NotifierTask; +import com.raytheon.uf.viz.collaboration.ui.notifier.NotifierTools; +import com.raytheon.uf.viz.collaboration.ui.session.AddNotifierDlg; +import com.raytheon.viz.ui.dialogs.ICloseCallback; + +/** + * Contact Notifier preferences page. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Feb 20, 2014   2632     mpduff      Initial creation
+ * 
+ * 
+ * + * @author mpduff + * @version 1.0 + */ + +public class ContactNotifierPreferencePage extends PreferencePage implements + IWorkbenchPreferencePage { + /** The notifier list control */ + private org.eclipse.swt.widgets.List notifierList; + + /** Delete notifier button */ + private Button deleteBtn; + + /** Edit notifier button */ + private Button editBtn; + + /** New notifier button */ + private Button newBtn; + + /** Notifier task list */ + private java.util.List taskList = NotifierTools + .getNotifierTasks(); + + /** Data map backing the notifier list */ + private final Map dataMap = new HashMap(); + + /** + * {@inheritDoc} + */ + @Override + public void init(IWorkbench workbench) { + setPreferenceStore(Activator.getDefault().getPreferenceStore()); + } + + /** + * {@inheritDoc} + */ + @Override + protected Control createContents(Composite parent) { + GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); + gd.horizontalSpan = 3; + gd.heightHint = 150; + + notifierList = new org.eclipse.swt.widgets.List(parent, SWT.BORDER + | SWT.V_SCROLL); + notifierList.setLayoutData(gd); + notifierList.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + setButtonState(); + } + }); + + Composite buttonComp = new Composite(parent, SWT.NONE); + buttonComp.setLayout(new GridLayout(3, false)); + gd = new GridData(SWT.RIGHT, SWT.FILL, true, true); + gd.horizontalSpan = 3; + buttonComp.setLayoutData(gd); + + gd = new GridData(75, SWT.DEFAULT); + editBtn = new Button(buttonComp, SWT.PUSH); + editBtn.setText("Edit..."); + editBtn.setLayoutData(gd); + editBtn.setEnabled(false); + editBtn.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + editNotifierTask(); + } + }); + + gd = new GridData(75, SWT.DEFAULT); + newBtn = new Button(buttonComp, SWT.PUSH); + newBtn.setText("New..."); + newBtn.setLayoutData(gd); + newBtn.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + newNotifierTask(); + } + }); + + gd = new GridData(75, SWT.DEFAULT); + deleteBtn = new Button(buttonComp, SWT.PUSH); + deleteBtn.setText("Delete"); + deleteBtn.setLayoutData(gd); + deleteBtn.setEnabled(false); + deleteBtn.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + deleteNotifierTask(); + } + }); + + populate(); + + return null; + } + + /** + * Populate the list. + */ + private void populate() { + taskList = NotifierTools.getNotifierTasks(); + for (NotifierTask task : taskList) { + dataMap.put(task.getUserName(), task); + } + + Collection items = dataMap.keySet(); + List dataList = Lists.newArrayList(items); + Collections.sort(dataList); + notifierList.setItems(dataList.toArray(new String[0])); + } + + /** + * Edit the notifier task. + */ + private void editNotifierTask() { + String user = notifierList.getItem(notifierList.getSelectionIndex()); + NotifierTask task = dataMap.get(user); + if (task != null) { + AddNotifierDlg dlg = new AddNotifierDlg(getShell(), + new String[] { task.getUserName() }); + dlg.open(); + } + } + + /** + * Delete the notifier task. + */ + private void deleteNotifierTask() { + String user = notifierList.getItem(notifierList.getSelectionIndex()); + NotifierTask task = dataMap.get(user); + if (task != null) { + taskList.remove(task); + notifierList.remove(notifierList.getSelectionIndex()); + } + setButtonState(); + } + + /** + * Set the state of the buttons. + */ + private void setButtonState() { + if (notifierList.getSelectionCount() > 0) { + deleteBtn.setEnabled(true); + editBtn.setEnabled(true); + } else { + deleteBtn.setEnabled(false); + editBtn.setEnabled(false); + } + } + + /** + * Create a new notifier task. + */ + private void newNotifierTask() { + CollaborationConnection conn = CollaborationConnection.getConnection(); + if (conn != null) { + String[] contacts = getContacts(); + ICloseCallback callback = new ICloseCallback() { + @Override + public void dialogClosed(Object returnValue) { + populate(); + } + }; + AddNotifierDlg dlg = new AddNotifierDlg(getShell(), contacts, + callback); + dlg.open(); + } else { + MessageBox messageDialog = new MessageBox(this.getShell(), SWT.OK); + messageDialog.setText("Must Log In"); + messageDialog + .setMessage("User must be logged in to Collaboration to add contact notifiers."); + messageDialog.open(); + } + } + + /** + * Get the contacts. + * + * @return String[] of contacts + */ + private String[] getContacts() { + Set users = new HashSet(); + ContactsManager contactsManager = CollaborationConnection + .getConnection().getContactsManager(); + for (RosterGroup rg : contactsManager.getGroups()) { + for (RosterEntry re : rg.getEntries()) { + UserId userId = IDConverter.convertFrom(re); + users.add(userId.getName()); + } + } + + for (SharedGroup rg : contactsManager.getSharedGroups()) { + for (RosterEntry re : rg.getEntries()) { + UserId userId = IDConverter.convertFrom(re); + users.add(userId.getName()); + } + } + + for (RosterEntry re : contactsManager.getNonGroupedContacts()) { + UserId userId = IDConverter.convertFrom(re); + users.add(userId.getName()); + } + + return users.toArray(new String[users.size()]); + } + + @Override + public boolean performOk() { + NotifierTools.saveNotifiers(taskList); + return true; + } +} diff --git a/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/session/AbstractSessionView.java b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/session/AbstractSessionView.java index 12ba61395a..afd26b2404 100644 --- a/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/session/AbstractSessionView.java +++ b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/session/AbstractSessionView.java @@ -19,11 +19,6 @@ **/ package com.raytheon.uf.viz.collaboration.ui.session; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; @@ -58,15 +53,7 @@ import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Menu; import org.eclipse.ui.progress.IWorkbenchSiteProgressService; -import sun.audio.AudioData; -import sun.audio.AudioDataStream; -import sun.audio.AudioPlayer; -import sun.audio.AudioStream; - import com.google.common.eventbus.Subscribe; -import com.raytheon.uf.common.status.IUFStatusHandler; -import com.raytheon.uf.common.status.UFStatus; -import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.time.util.TimeUtil; import com.raytheon.uf.viz.collaboration.comm.identity.IMessage; import com.raytheon.uf.viz.collaboration.comm.identity.user.IUser; @@ -82,6 +69,7 @@ import com.raytheon.uf.viz.collaboration.ui.data.AlertWord; import com.raytheon.uf.viz.collaboration.ui.prefs.CollabPrefConstants; import com.raytheon.uf.viz.core.VizApp; import com.raytheon.uf.viz.core.icon.IconUtil; +import com.raytheon.uf.viz.core.sounds.SoundUtil; import com.raytheon.viz.ui.views.CaveFloatingView; /** @@ -99,6 +87,7 @@ import com.raytheon.viz.ui.views.CaveFloatingView; * Jan 30, 2014 2698 bclement get display name from child class * Feb 13, 2014 2751 bclement made generic * Feb 18, 2014 2631 mpduff Add ability to play sounds on join actions + * Feb 24, 2014 2632 mpduff Moved sound generation code to CollaborationUtils * * * @@ -108,9 +97,6 @@ import com.raytheon.viz.ui.views.CaveFloatingView; public abstract class AbstractSessionView extends CaveFloatingView { - private static final transient IUFStatusHandler statusHandler = UFStatus - .getHandler(AbstractSessionView.class); - private static final String SESSION_IMAGE_KEY = "sessionId.key"; private static ThreadLocal dateFormatter = TimeUtil @@ -135,8 +121,6 @@ public abstract class AbstractSessionView extends private List alertWords = null; - private AudioDataStream ads = null; - private Map fonts = null; private Map colors = null; @@ -475,53 +459,8 @@ public abstract class AbstractSessionView extends playSound(filename); } - /** - * Play a sound. - * - * @param filename - * The file to play - */ protected void playSound(String filename) { - if (filename == null || filename.isEmpty()) { - return; - } - File soundFile = new File(filename); - InputStream in = null; - AudioStream as = null; - AudioData data = null; - try { - if (ads != null) { - AudioPlayer.player.stop(ads); - ads.close(); - ads = null; - } - in = new FileInputStream(soundFile); - as = new AudioStream(in); - data = as.getData(); - ads = new AudioDataStream(data); - AudioPlayer.player.start(ads); - } catch (FileNotFoundException e) { - statusHandler.handle(Priority.PROBLEM, "Unable to find sound file", - e); - } catch (IOException e) { - statusHandler.handle(Priority.PROBLEM, "Unable to read sound file", - e); - } finally { - try { - if (in != null) { - in.close(); - } - } catch (IOException e) { - // Ignore - } - try { - if (as != null) { - as.close(); - } - } catch (IOException e) { - // Ignore - } - } + SoundUtil.playSound(filename); } protected String getJoinFile() { @@ -581,13 +520,6 @@ public abstract class AbstractSessionView extends msgArchive = null; } - try { - if (ads != null) { - ads.close(); - } - } catch (IOException e) { - // Ignore - } super.dispose(); } diff --git a/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/session/AddNotifierDlg.java b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/session/AddNotifierDlg.java new file mode 100644 index 0000000000..dd6582633a --- /dev/null +++ b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/session/AddNotifierDlg.java @@ -0,0 +1,436 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.viz.collaboration.ui.session; + +import java.io.File; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Layout; +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +import com.google.common.collect.Lists; +import com.raytheon.uf.common.localization.LocalizationContext; +import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; +import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; +import com.raytheon.uf.common.localization.LocalizationFile; +import com.raytheon.uf.common.localization.PathManager; +import com.raytheon.uf.common.localization.PathManagerFactory; +import com.raytheon.uf.common.util.StringUtil; +import com.raytheon.uf.viz.collaboration.ui.notifier.Notifier; +import com.raytheon.uf.viz.collaboration.ui.notifier.NotifierTask; +import com.raytheon.uf.viz.collaboration.ui.notifier.NotifierTools; +import com.raytheon.uf.viz.core.sounds.SoundUtil; +import com.raytheon.viz.ui.dialogs.CaveSWTDialog; +import com.raytheon.viz.ui.dialogs.ICloseCallback; + +/** + * Add Notifier Dialog. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Feb 20, 2014    2632    mpduff      Initial creation
+ * 
+ * 
+ * + * @author mpduff + * @version 1.0 + */ + +public class AddNotifierDlg extends CaveSWTDialog { + + /** Array of userIds */ + private final String[] userIds; + + /** Map of buttons to Notifiers */ + private final Map buttonMap = new HashMap(); + + /** Set of NotifierTask objects */ + private final Set taskSet = new HashSet(); + + /** The user select Combo box */ + private Combo userCbo; + + /** The sound file path text widget */ + private Text soundTxt; + + /** Recurring radio button */ + private Button recurringRdo; + + /** Close callback */ + private final ICloseCallback callback; + + /** The class return value */ + private boolean returnValue = false; + + /** + * Constructor. + * + * @param parent + * @param userIds + * @param callback + */ + public AddNotifierDlg(Shell parent, String[] userIds, + ICloseCallback callback) { + super(parent, SWT.DIALOG_TRIM, CAVE.DO_NOT_BLOCK); + setText("Add Notifier"); + this.userIds = userIds; + this.callback = callback; + } + + public AddNotifierDlg(Shell parent, String[] userIds) { + this(parent, userIds, null); + } + + /* + * (non-Javadoc) + * + * @see com.raytheon.viz.ui.dialogs.CaveSWTDialogBase#constructShellLayout() + */ + @Override + protected Layout constructShellLayout() { + GridLayout mainLayout = new GridLayout(1, true); + mainLayout.marginHeight = 4; + mainLayout.marginWidth = 4; + return mainLayout; + } + + /** + * {@inheritDoc} + */ + @Override + protected void initializeComponents(Shell shell) { + createUserComp(shell); + createActionComp(shell); + createBtnComp(shell); + } + + /** + * Create the user composite. + * + * @param shell + */ + private void createUserComp(Shell shell) { + GridLayout gl = new GridLayout(2, false); + GridData gd = new GridData(SWT.LEFT, SWT.DEFAULT, false, false); + Composite userComp = new Composite(shell, SWT.NONE); + userComp.setLayout(gl); + userComp.setLayoutData(gd); + + gd = new GridData(SWT.LEFT, SWT.CENTER, false, false); + Label userLbl = new Label(userComp, SWT.NONE); + userLbl.setText("Add Notifier to: "); + userLbl.setLayoutData(gd); + + gd = new GridData(165, SWT.DEFAULT); + userCbo = new Combo(userComp, SWT.NONE); + userCbo.setLayoutData(gd); + userCbo.setItems(getUserIds()); + userCbo.select(0); + userCbo.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + NotifierTask task = NotifierTools.getNotifierTask(userCbo + .getText()); + if (task != null) { + populate(task); + } else { + reset(); + } + } + }); + } + + /** + * Create the action composite + * + * @param shell + */ + private void createActionComp(Shell shell) { + GridLayout gl = new GridLayout(1, false); + GridData gd = new GridData(SWT.LEFT, SWT.DEFAULT, false, false); + Composite lblComp = new Composite(shell, SWT.NONE); + lblComp.setLayout(gl); + lblComp.setLayoutData(gd); + + gd = new GridData(SWT.LEFT, SWT.CENTER, false, false); + Label actionLbl = new Label(lblComp, SWT.NONE); + actionLbl.setText("Notify when Contact..."); + actionLbl.setLayoutData(gd); + + gd = new GridData(SWT.LEFT, SWT.CENTER, false, false); + gd.horizontalIndent = 20; + gl = new GridLayout(2, false); + Composite btnComp = new Composite(shell, SWT.NONE); + btnComp.setLayout(gl); + btnComp.setLayoutData(gd); + + for (Notifier notifier : Notifier.values()) { + Button chk = new Button(btnComp, SWT.CHECK); + chk.setText(notifier.getDescription()); + chk.setData(notifier); + buttonMap.put(chk, notifier); + } + + gd = new GridData(SWT.LEFT, SWT.CENTER, false, false); + gl = new GridLayout(1, false); + Composite lblComp2 = new Composite(shell, SWT.NONE); + lblComp2.setLayout(gl); + lblComp2.setLayoutData(gd); + + gd = new GridData(SWT.LEFT, SWT.CENTER, false, false); + Label soundLbl = new Label(lblComp2, SWT.NONE); + soundLbl.setText("Play this sound: "); + soundLbl.setLayoutData(gd); + + gd = new GridData(SWT.LEFT, SWT.CENTER, false, false); + gd.horizontalIndent = 20; + gl = new GridLayout(3, false); + Composite soundComp = new Composite(shell, SWT.NONE); + soundComp.setLayout(gl); + soundComp.setLayoutData(gd); + + gd = new GridData(175, SWT.DEFAULT); + soundTxt = new Text(soundComp, SWT.BORDER); + soundTxt.setLayoutData(gd); + + gd = new GridData(75, SWT.DEFAULT); + Button browseBtn = new Button(soundComp, SWT.PUSH); + browseBtn.setText("Browse..."); + browseBtn.setLayoutData(gd); + browseBtn.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + PathManager manager = (PathManager) PathManagerFactory + .getPathManager(); + LocalizationContext context = manager.getContext( + LocalizationType.CAVE_STATIC, LocalizationLevel.USER); + LocalizationFile file = manager.getLocalizationFile(context, + "collaboration" + File.separator + "sounds" + + File.separator); + if (!file.exists()) { + file.getFile().mkdirs(); + } + + FileDialog fileDlg = new FileDialog(Display.getCurrent() + .getActiveShell(), SWT.OPEN); + fileDlg.setFilterPath(file.getFile().getAbsolutePath()); + String filePath = fileDlg.open(); + if (!StringUtil.isEmptyString(filePath)) { + soundTxt.setText(filePath); + } + } + }); + + gd = new GridData(75, SWT.DEFAULT); + Button previewBtn = new Button(soundComp, SWT.PUSH); + previewBtn.setText("Preview"); + previewBtn.setLayoutData(gd); + previewBtn.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + String soundFile = soundTxt.getText().trim(); + if (soundFile.length() > 0) { + SoundUtil.playSound(soundFile); + } + } + }); + + gd = new GridData(SWT.LEFT, SWT.CENTER, false, false); + Label freqLabel = new Label(shell, SWT.NONE); + freqLabel.setText("Notifier Frequency: "); + freqLabel.setLayoutData(gd); + + gd = new GridData(SWT.LEFT, SWT.CENTER, false, false); + gd.horizontalIndent = 20; + gl = new GridLayout(2, false); + Composite freqComp = new Composite(shell, SWT.NONE); + freqComp.setLayout(gl); + freqComp.setLayoutData(gd); + + gd = new GridData(SWT.DEFAULT, SWT.TOP, false, true); + Button singleRdo = new Button(freqComp, SWT.RADIO); + singleRdo.setLayoutData(gd); + singleRdo.setText("Single Instance"); + singleRdo.setSelection(true); + + gd = new GridData(SWT.DEFAULT, SWT.TOP, false, true); + recurringRdo = new Button(freqComp, SWT.RADIO); + recurringRdo.setLayoutData(gd); + recurringRdo.setText("Recurring"); + } + + private void createBtnComp(Shell shell) { + Label sl = new Label(shell, SWT.HORIZONTAL | SWT.SEPARATOR); + sl.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + GridLayout gl = new GridLayout(2, false); + GridData gd = new GridData(SWT.CENTER, SWT.DEFAULT, false, false); + Composite comp = new Composite(shell, SWT.NONE); + comp.setLayout(gl); + comp.setLayoutData(gd); + + GridData btnData = new GridData(75, SWT.DEFAULT); + Button addBtn = new Button(comp, SWT.PUSH); + addBtn.setText("Add"); + addBtn.setLayoutData(btnData); + addBtn.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + addNotifierTask(); + returnValue = true; + } + }); + + btnData = new GridData(75, SWT.DEFAULT); + Button cancelBtn = new Button(comp, SWT.PUSH); + cancelBtn.setText("Close"); + cancelBtn.setLayoutData(btnData); + cancelBtn.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + returnValue = false; + close(); + } + }); + } + + /* + * (non-Javadoc) + * + * @see com.raytheon.viz.ui.dialogs.CaveSWTDialogBase#opened() + */ + @Override + protected void opened() { + // Check for existing notifiers + List taskList = NotifierTools.getNotifierTasks(); + + for (NotifierTask task : taskList) { + taskSet.add(task); + if (task.getUserName().equals(userCbo.getText())) { + this.populate(task); + return; + } + } + } + + /** + * Populate the controls based on the provided task. + * + * @param task + * The task to populate the controls from + */ + private void populate(NotifierTask task) { + for (Button b : buttonMap.keySet()) { + if (task.getNotifierList().contains(b.getData())) { + b.setSelection(true); + } + } + + soundTxt.setText(task.getSoundFilePath()); + } + + /** + * Reset the dialog controls. + */ + protected void reset() { + for (Button b : buttonMap.keySet()) { + b.setSelection(false); + } + + soundTxt.setText(""); + } + + /** + * Get the user ids + * + * @return Array of user ids + */ + private String[] getUserIds() { + String[] usernames = new String[this.userIds.length]; + for (int i = 0; i < userIds.length; i++) { + usernames[i] = userIds[i]; + } + + return usernames; + } + + /** + * Add a notifier task based on the setting in the dialog. + */ + private void addNotifierTask() { + NotifierTask task = new NotifierTask(); + task.setUserName(userCbo.getText()); + task.setSoundFilePath(soundTxt.getText()); + for (Button b : buttonMap.keySet()) { + if (b.getSelection()) { + task.addNotifier((Notifier) b.getData()); + } + } + + task.setRecurring(recurringRdo.getSelection()); + + taskSet.add(task); + + if (NotifierTools.saveNotifiers(Lists.newArrayList(taskSet))) { + MessageBox messageDialog = new MessageBox(this.getShell(), SWT.OK); + messageDialog.setText("Notifier Saved"); + messageDialog + .setMessage("The contact notifier was successfully saved."); + messageDialog.open(); + } else { + MessageBox messageDialog = new MessageBox(this.getShell(), SWT.OK); + messageDialog.setText("Save Failed"); + messageDialog.setMessage("The contact notifier failed to save."); + messageDialog.open(); + } + } + + /* + * (non-Javadoc) + * + * @see com.raytheon.viz.ui.dialogs.CaveSWTDialogBase#disposed() + */ + @Override + protected void disposed() { + if (this.callback != null) { + callback.dialogClosed(returnValue); + } + } +} diff --git a/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/session/PeerToPeerView.java b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/session/PeerToPeerView.java index 99400d9dbf..4ff24e68de 100644 --- a/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/session/PeerToPeerView.java +++ b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/session/PeerToPeerView.java @@ -40,11 +40,15 @@ import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.viz.collaboration.comm.identity.CollaborationException; +import com.raytheon.uf.viz.collaboration.comm.identity.IMessage; import com.raytheon.uf.viz.collaboration.comm.identity.IPeerToPeer; import com.raytheon.uf.viz.collaboration.comm.provider.session.CollaborationConnection; import com.raytheon.uf.viz.collaboration.comm.provider.user.RosterItem; import com.raytheon.uf.viz.collaboration.comm.provider.user.UserId; import com.raytheon.uf.viz.collaboration.ui.actions.PrintLogActionContributionItem; +import com.raytheon.uf.viz.collaboration.ui.notifier.NotifierTask; +import com.raytheon.uf.viz.collaboration.ui.notifier.NotifierTools; +import com.raytheon.uf.viz.core.sounds.SoundUtil; /** * UI display for one-on-one chat sessions @@ -58,6 +62,7 @@ import com.raytheon.uf.viz.collaboration.ui.actions.PrintLogActionContributionIt * Mar 1, 2012 rferrel Initial creation * Jan 30, 2014 2698 bclement added getDisplayName * Feb 13, 2014 2751 bclement made parent generic + * Feb 28, 2014 2632 mpduff Override appendMessage for notifiers * * * @@ -119,6 +124,27 @@ public class PeerToPeerView extends AbstractSessionView implements sashForm.setWeights(new int[] { 20, 5 }); } + /* + * (non-Javadoc) + * + * @see com.raytheon.uf.viz.collaboration.ui.session.AbstractSessionView# + * appendMessage(com.raytheon.uf.viz.collaboration.comm.identity.IMessage) + */ + @Override + public void appendMessage(IMessage message) { + // Check for message notifiers + NotifierTask task = NotifierTools.getNotifierTask(message.getFrom() + .getName()); + if (task != null && task.containsSendMessage()) { + if (task.isSoundValid()) { + SoundUtil.playSound(task.getSoundFilePath()); + NotifierTools.taskExecuted(task); + } + } + + super.appendMessage(message); + } + /* * (non-Javadoc) * diff --git a/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/session/SessionView.java b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/session/SessionView.java index e2dc48f635..1255d765eb 100644 --- a/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/session/SessionView.java +++ b/cave/com.raytheon.uf.viz.collaboration.ui/src/com/raytheon/uf/viz/collaboration/ui/session/SessionView.java @@ -82,6 +82,7 @@ import com.raytheon.uf.viz.collaboration.ui.Activator; import com.raytheon.uf.viz.collaboration.ui.actions.PrintLogActionContributionItem; import com.raytheon.uf.viz.collaboration.ui.prefs.CollabPrefConstants; import com.raytheon.uf.viz.core.VizApp; +import com.raytheon.uf.viz.core.sounds.SoundUtil; import com.raytheon.viz.ui.views.CaveWorkbenchPageManager; /** @@ -100,6 +101,7 @@ import com.raytheon.viz.ui.views.CaveWorkbenchPageManager; * Jan 28, 2014 2698 bclement removed venue info * Feb 13, 2014 2751 bclement VenueParticipant refactor * Feb 18, 2014 2631 mpduff Add processJoinAlert() + * Feb 24, 2014 2632 mpduff Move playSound to CollaborationUtils * * * @@ -785,10 +787,13 @@ public class SessionView extends AbstractSessionView * Process a room join alert. */ protected void processJoinAlert() { - boolean enabled = Activator.getDefault().getPreferenceStore() - .getBoolean(CollabPrefConstants.ENABLE_JOIN_EVENTS_FIELD_EDITOR_ID); + boolean enabled = Activator + .getDefault() + .getPreferenceStore() + .getBoolean( + CollabPrefConstants.ENABLE_JOIN_EVENTS_FIELD_EDITOR_ID); if (enabled) { - this.playSound(getJoinFile()); + SoundUtil.playSound(getJoinFile()); } } } diff --git a/cave/com.raytheon.uf.viz.core/META-INF/MANIFEST.MF b/cave/com.raytheon.uf.viz.core/META-INF/MANIFEST.MF index 777a170768..d5ef0fca12 100644 --- a/cave/com.raytheon.uf.viz.core/META-INF/MANIFEST.MF +++ b/cave/com.raytheon.uf.viz.core/META-INF/MANIFEST.MF @@ -78,6 +78,7 @@ Export-Package: com.raytheon.uf.viz.core, com.raytheon.uf.viz.core.rsc.hdf5, com.raytheon.uf.viz.core.rsc.updater, com.raytheon.uf.viz.core.sampling, + com.raytheon.uf.viz.core.sounds, com.raytheon.uf.viz.core.status, com.raytheon.uf.viz.core.tile, com.raytheon.uf.viz.core.time, diff --git a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/sounds/SoundUtil.java b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/sounds/SoundUtil.java new file mode 100644 index 0000000000..243d587862 --- /dev/null +++ b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/sounds/SoundUtil.java @@ -0,0 +1,105 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.viz.core.sounds; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import sun.audio.AudioData; +import sun.audio.AudioDataStream; +import sun.audio.AudioPlayer; +import sun.audio.AudioStream; + +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.status.UFStatus.Priority; + +/** + * Utility class for playing sounds. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Feb 24, 2014   2636     mpduff      Initial creation
+ * 
+ * 
+ * + * @author mpduff + * @version 1.0 + */ + +public class SoundUtil { + private static final IUFStatusHandler statusHandler = UFStatus + .getHandler(SoundUtil.class); + + /** AudioDataStream object */ + private static AudioDataStream ads = null; + + /** + * Play a sound from the file at the provided path. + * + * @param filename + * The filename path + */ + public static void playSound(String filename) { + if (filename == null || filename.isEmpty()) { + return; + } + File soundFile = new File(filename); + InputStream in = null; + AudioStream as = null; + AudioData data = null; + try { + if (ads != null) { + AudioPlayer.player.stop(ads); + ads.close(); + ads = null; + } + in = new FileInputStream(soundFile); + as = new AudioStream(in); + data = as.getData(); + ads = new AudioDataStream(data); + AudioPlayer.player.start(ads); + } catch (IOException e) { + statusHandler.handle(Priority.PROBLEM, "Unable to read sound file", + e); + } finally { + try { + if (in != null) { + in.close(); + } + } catch (IOException e) { + // Ignore + } + try { + if (as != null) { + as.close(); + } + } catch (IOException e) { + // Ignore + } + } + } +}