Issue #663 Fixed clearing of display in D2D, resources can now be specified to be readded when unloaded during a session

Change-Id: I77b448ad4af60bf8d1afb3b50a5575ad82c4ae22

Former-commit-id: 8773dbdf62 [formerly d15821c57b49090863e9c22455d06c94da6fcaf9]
Former-commit-id: f6f2e1a4fb
This commit is contained in:
Max Schenkelberg 2012-05-25 14:37:25 -05:00
parent 0211167d87
commit dec7ce3551
35 changed files with 2410 additions and 2776 deletions

View file

@ -1,4 +1,6 @@
com.raytheon.uf.viz.collaboration.ui.editor.SharedResource
com.raytheon.uf.viz.collaboration.ui.rsc.CollaborationResourceData
com.raytheon.uf.viz.collaboration.ui.rsc.DataProviderRscData
com.raytheon.uf.viz.collaboration.ui.rsc.CollaborationWrapperResourceData
com.raytheon.uf.viz.collaboration.ui.telestrator.CollaborationPathDrawingResourceData
com.raytheon.uf.viz.collaboration.ui.telestrator.CollaborationPathDrawingResourceData
com.raytheon.uf.viz.collaboration.ui.telestrator.CollaborationDrawingResourceData

View file

@ -184,5 +184,58 @@
id="com.raytheon.uf.viz.collaboration.ui.prefs.collaborationalertwordspreferencepage"
name="Significant Words"
category="com.raytheon.uf.viz.collaboration.ui.prefs.collaborationpreferencepage"/>
</extension>
<extension
point="org.eclipse.ui.contexts">
<context
description="Collaboration Drawing Context"
id="com.raytheon.uf.viz.collaboration.tellestrator.context"
name="Collaboration Drawing Context">
</context>
</extension>
<extension
point="org.eclipse.ui.commands">
<command
id="com.raytheon.uf.viz.collaboration.tellestrator.undoRedo"
name="Undo/Redo command">
<commandParameter
id="com.raytheon.uf.viz.collaboration.tellestrator.action"
name="Undo/Redo Action"
optional="false">
</commandParameter>
</command>
</extension>
<extension
point="org.eclipse.ui.handlers">
<handler
class="com.raytheon.uf.viz.collaboration.ui.telestrator.handlers.UndoRedoHandler"
commandId="com.raytheon.uf.viz.collaboration.tellestrator.undoRedo">
</handler>
</extension>
<extension
point="org.eclipse.ui.bindings">
<key
commandId="com.raytheon.uf.viz.collaboration.tellestrator.undoRedo"
contextId="com.raytheon.uf.viz.collaboration.tellestrator.context"
schemeId="com.raytheon.viz.ui.awips.scheme"
sequence="M1+Z">
<parameter id="com.raytheon.uf.viz.collaboration.tellestrator.action" value="UNDO"/>
</key>
<key
commandId="com.raytheon.uf.viz.collaboration.tellestrator.undoRedo"
contextId="com.raytheon.uf.viz.collaboration.tellestrator.context"
schemeId="com.raytheon.viz.ui.awips.scheme"
sequence="M1+Y">
<parameter id="com.raytheon.uf.viz.collaboration.tellestrator.action" value="REDO"/>
</key>
</extension>
<extension
point="com.raytheon.uf.viz.core.classContext">
<classContext
class="com.raytheon.uf.viz.collaboration.ui.telestrator.CollaborationDrawingToolbar">
<contextId
id="com.raytheon.uf.viz.collaboration.tellestrator.context">
</contextId>
</classContext>
</extension>
</plugin>

View file

@ -120,7 +120,6 @@ import com.raytheon.uf.viz.collaboration.ui.session.AbstractSessionView;
import com.raytheon.uf.viz.collaboration.ui.session.CollaborationSessionView;
import com.raytheon.uf.viz.collaboration.ui.session.PeerToPeerView;
import com.raytheon.uf.viz.collaboration.ui.session.SessionView;
import com.raytheon.uf.viz.collaboration.ui.telestrator.CollaborationPathToolbar;
import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.uf.viz.core.icon.IconUtil;
import com.raytheon.viz.ui.VizWorkbenchManager;
@ -477,7 +476,8 @@ public class CollaborationGroupView extends ViewPart implements IPartListener {
drawToolbarAction = new Action("Drawing Toolbar") {
@Override
public void run() {
CollaborationPathToolbar.getToolbar().open();
// TODO: What is this?
System.err.println("What is this method!?");
}
};
drawToolbarAction.setImageDescriptor(IconUtil.getImageDescriptor(
@ -1378,7 +1378,7 @@ public class CollaborationGroupView extends ViewPart implements IPartListener {
createSessionAction.setEnabled(isSessionEnabled);
}
}
/**
* Adds users to groups if necessary
*

View file

@ -28,13 +28,9 @@ import org.eclipse.swt.graphics.Rectangle;
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.ISharedDisplaySession;
import com.raytheon.uf.viz.collaboration.comm.identity.IVenueSession;
import com.raytheon.uf.viz.collaboration.display.editor.CollaborationEditor;
import com.raytheon.uf.viz.collaboration.display.editor.SharedEditorData;
import com.raytheon.uf.viz.collaboration.ui.rsc.CollaborationWrapperResource;
import com.raytheon.uf.viz.collaboration.ui.rsc.DataProviderRsc;
import com.raytheon.uf.viz.core.IExtent;
import com.raytheon.uf.viz.core.PixelExtent;
import com.raytheon.uf.viz.core.drawables.AbstractRenderableDisplay;
@ -44,7 +40,6 @@ import com.raytheon.uf.viz.core.drawables.ResourcePair;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.map.MapDescriptor;
import com.raytheon.uf.viz.core.maps.display.PlainMapRenderableDisplay;
import com.raytheon.uf.viz.core.rsc.GenericResourceData;
import com.raytheon.viz.ui.UiUtil;
import com.raytheon.viz.ui.editor.AbstractEditor;
import com.vividsolutions.jts.geom.Envelope;
@ -153,49 +148,4 @@ public class EditorSetup {
return editor;
}
/**
* Initializes the resources necessary to share the editor with others
* connected to the collaboration session.
*
* @param session
* the session to share the editor with
* @param editor
* the editor to share
* @throws CollaborationException
*/
public static void shareEditor(ISharedDisplaySession session,
AbstractEditor editor) throws CollaborationException {
if (!session.getUserID().equals(session.getCurrentDataProvider())) {
throw new CollaborationException(
"Incorrect role to share an editor");
} else if (editor instanceof CollaborationEditor) {
throw new CollaborationException(
"Cannot share a CollaborationEditor");
}
addIndicator(editor, session);
// TODO this method should be called by the ShareEditorAction
// TODO should max's target injection be over here too?
}
private static void addIndicator(AbstractEditor editor,
ISharedDisplaySession session) {
IDescriptor desc = editor.getActiveDisplayPane().getRenderableDisplay()
.getDescriptor();
GenericResourceData grd = new GenericResourceData(DataProviderRsc.class);
ResourcePair rp = new ResourcePair();
rp.setResourceData(grd);
desc.getResourceList().add(rp);
desc.getResourceList().instantiateResources(desc, true);
DataProviderRsc rsc = (DataProviderRsc) rp.getResource();
rsc.setRoomName(((IVenueSession) session).getVenue().getInfo()
.getVenueDescription());
rsc.setSubject(((IVenueSession) session).getVenue().getInfo()
.getVenueSubject());
rsc.setSession(session);
}
}

View file

@ -19,12 +19,29 @@
**/
package com.raytheon.uf.viz.collaboration.ui.role;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IWorkbenchPart;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.collaboration.comm.identity.ISharedDisplaySession;
import com.raytheon.uf.viz.collaboration.ui.telestrator.CollaborationPathDrawingTool;
import com.raytheon.uf.viz.collaboration.ui.telestrator.CollaborationPathToolbar;
import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.uf.viz.drawing.PathToolbar;
import com.raytheon.uf.viz.drawing.tools.PathDrawingTool;
import com.raytheon.uf.viz.collaboration.ui.Activator;
import com.raytheon.uf.viz.collaboration.ui.telestrator.CollaborationDrawingResource;
import com.raytheon.uf.viz.collaboration.ui.telestrator.CollaborationDrawingResourceData;
import com.raytheon.uf.viz.core.IDisplayPane;
import com.raytheon.uf.viz.core.drawables.IDescriptor;
import com.raytheon.uf.viz.core.drawables.ResourcePair;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.LoadProperties;
import com.raytheon.uf.viz.core.rsc.ResourceList;
import com.raytheon.uf.viz.core.rsc.ResourceList.RemoveListener;
import com.raytheon.uf.viz.core.rsc.ResourceProperties;
import com.raytheon.viz.ui.editor.AbstractEditor;
/**
* Abstract role event controller that shares fields and methods that are common
@ -45,11 +62,13 @@ import com.raytheon.uf.viz.drawing.tools.PathDrawingTool;
*/
public abstract class AbstractRoleEventController implements
IRoleEventController {
IRoleEventController, IPartListener, RemoveListener {
protected ISharedDisplaySession session;
private PathDrawingTool tool;
protected List<ResourcePair> resourcesAdded = new ArrayList<ResourcePair>();
private List<AbstractEditor> resourceEditors = new CopyOnWriteArrayList<AbstractEditor>();
protected AbstractRoleEventController(ISharedDisplaySession session) {
this.session = session;
@ -63,34 +82,133 @@ public abstract class AbstractRoleEventController implements
@Override
public void shutdown() {
session.unRegisterEventHandler(this);
}
protected void activateTelestrator() {
VizApp.runAsync(new Runnable() {
@Override
public void run() {
// activate the drawing tool by default for the session leader
tool = new CollaborationPathDrawingTool();
((CollaborationPathDrawingTool) tool).setSession(session
.getSessionId());
tool.activate();
session.registerEventHandler(tool);
// open the path drawing toolbar
PathToolbar toolbar = CollaborationPathToolbar.getToolbar();
toolbar.open();
// Orphaned tellestrators, not sure what to do yet about clear
for (AbstractEditor editor : resourceEditors) {
partClosed(editor);
}
for (ResourcePair rp : resourcesAdded) {
CollaborationDrawingResource resource = (CollaborationDrawingResource) rp
.getResource();
if (resource != null) {
resource.getDescriptor().getResourceList()
.removePostRemoveListener(this);
resource.unload();
}
});
}
resourcesAdded.clear();
resourceEditors.clear();
}
protected void deactivateTelestrator() {
// TODO this must be handled better
CollaborationPathToolbar.getToolbar().close();
if (tool != null) {
tool.deactivate();
session.unRegisterEventHandler(tool);
protected void activateResources(AbstractEditor editor) {
for (IDisplayPane pane : editor.getDisplayPanes()) {
try {
IDescriptor descriptor = pane.getDescriptor();
for (ResourcePair resource : getResourcesToAdd()) {
if (resource.getResource() == null) {
resource.setResource(resource.getResourceData()
.construct(resource.getLoadProperties(),
descriptor));
}
descriptor.getResourceList().add(resource);
descriptor.getResourceList().addPostRemoveListener(this);
resourcesAdded.add(resource);
}
} catch (VizException e) {
Activator.statusHandler.handle(Priority.PROBLEM,
"Error adding drawing resource to pane", e);
}
}
resourceEditors.add(editor);
editor.getSite().getPage().addPartListener(this);
}
protected void deactivateResources(AbstractEditor editor) {
partClosed(editor);
editor.getSite().getPage().removePartListener(this);
}
protected List<ResourcePair> getResourcesToAdd() {
List<ResourcePair> resources = new ArrayList<ResourcePair>();
CollaborationDrawingResourceData resourceData = new CollaborationDrawingResourceData();
resourceData.setSessionId(session.getSessionId());
ResourcePair resource = new ResourcePair();
resource.setResourceData(resourceData);
resource.setProperties(new ResourceProperties());
resource.setLoadProperties(new LoadProperties());
resources.add(resource);
return resources;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.rsc.ResourceList.RemoveListener#notifyRemove
* (com.raytheon.uf.viz.core.drawables.ResourcePair)
*/
@Override
public void notifyRemove(ResourcePair rp) throws VizException {
if (resourcesAdded.contains(rp)) {
try {
Class<?> clazz = rp.getResource().getClass();
Constructor<?> constructor = clazz.getConstructor(clazz);
ResourcePair newPair = new ResourcePair();
newPair.setLoadProperties(rp.getLoadProperties());
newPair.setProperties(rp.getProperties());
newPair.setResourceData(rp.getResourceData());
newPair.setResource((AbstractVizResource<?, ?>) constructor
.newInstance(rp.getResource()));
rp.getResource().getDescriptor().getResourceList().add(newPair);
} catch (Exception e) {
Activator.statusHandler
.handle(Priority.PROBLEM,
"Cannot manage resources from being unloaded that do not have copy constructor",
e);
}
}
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ui.IPartListener#partClosed(org.eclipse.ui.IWorkbenchPart)
*/
@Override
public void partClosed(IWorkbenchPart part) {
for (AbstractEditor editor : resourceEditors) {
if (editor == part) {
for (IDisplayPane pane : editor.getDisplayPanes()) {
ResourceList list = pane.getDescriptor().getResourceList();
list.removePostRemoveListener(this);
for (ResourcePair rp : list) {
if (resourcesAdded.contains(rp)) {
resourcesAdded.remove(rp);
list.remove(rp);
}
}
}
resourceEditors.remove(editor);
}
}
}
// Unneeded part events
@Override
public void partActivated(IWorkbenchPart part) {
}
@Override
public void partBroughtToTop(IWorkbenchPart part) {
}
@Override
public void partDeactivated(IWorkbenchPart part) {
}
@Override
public void partOpened(IWorkbenchPart part) {
}
}

View file

@ -19,7 +19,6 @@
**/
package com.raytheon.uf.viz.collaboration.ui.role;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
@ -49,17 +48,17 @@ import com.raytheon.uf.viz.collaboration.ui.editor.event.InputEvent;
import com.raytheon.uf.viz.collaboration.ui.role.dataprovider.CollaborationDispatcher;
import com.raytheon.uf.viz.collaboration.ui.rsc.CollaborationWrapperResource;
import com.raytheon.uf.viz.collaboration.ui.rsc.CollaborationWrapperResourceData;
import com.raytheon.uf.viz.collaboration.ui.rsc.DataProviderRsc;
import com.raytheon.uf.viz.collaboration.ui.telestrator.CollaborationDrawingLayer;
import com.raytheon.uf.viz.collaboration.ui.rsc.DataProviderRscData;
import com.raytheon.uf.viz.core.IDisplayPane;
import com.raytheon.uf.viz.core.IDisplayPaneContainer;
import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.uf.viz.core.drawables.IRenderableDisplay;
import com.raytheon.uf.viz.core.drawables.ResourcePair;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.rsc.LoadProperties;
import com.raytheon.uf.viz.core.rsc.ResourceList;
import com.raytheon.uf.viz.core.rsc.ResourceList.AddListener;
import com.raytheon.uf.viz.core.rsc.ResourceList.RemoveListener;
import com.raytheon.uf.viz.core.rsc.ResourceProperties;
import com.raytheon.uf.viz.remote.graphics.Dispatcher;
import com.raytheon.uf.viz.remote.graphics.DispatcherFactory;
import com.raytheon.uf.viz.remote.graphics.DispatchingGraphicsFactory;
@ -239,16 +238,17 @@ public class DataProviderEventController extends AbstractRoleEventController {
public void startup() {
super.startup();
SessionColorManager manager = SharedDisplaySessionMgr
.getSessionContainer(session.getSessionId()).getColorManager();
SessionContainer sessionContainer = SharedDisplaySessionMgr
.getSessionContainer(session.getSessionId());
SessionColorManager manager = sessionContainer.getColorManager();
manager.addUser(session.getCurrentDataProvider());
super.activateTelestrator();
wrappingListener = new ResourceWrapperListener();
for (IDisplayPaneContainer container : SharedDisplaySessionMgr
.getSessionContainer(session.getSessionId()).getSharedEditors()) {
for (AbstractEditor editor : sessionContainer.getSharedEditors()) {
super.activateResources(editor);
// Replace pane resources that will be shared with
// CollaborationWrapperResource objects
for (IDisplayPane pane : container.getDisplayPanes()) {
for (IDisplayPane pane : editor.getDisplayPanes()) {
ResourceList list = pane.getDescriptor().getResourceList();
for (ResourcePair rp : pane.getDescriptor().getResourceList()) {
wrapResourcePair(rp);
@ -258,7 +258,7 @@ public class DataProviderEventController extends AbstractRoleEventController {
}
// Inject remote graphics functionality in container
DispatchingGraphicsFactory.injectRemoteFunctionality(container,
DispatchingGraphicsFactory.injectRemoteFunctionality(editor,
new DispatcherFactory() {
@Override
public Dispatcher createNewDispatcher(
@ -276,17 +276,29 @@ public class DataProviderEventController extends AbstractRoleEventController {
}
}
});
try {
EditorSetup.shareEditor(session, (AbstractEditor) container);
} catch (CollaborationException e) {
// TODO Auto-generated catch block. Please revise as
// appropriate.
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
e);
}
}
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.collaboration.ui.role.AbstractRoleEventController
* #getResourcesToAdd()
*/
@Override
protected List<ResourcePair> getResourcesToAdd() {
List<ResourcePair> resources = super.getResourcesToAdd();
ResourcePair resource = new ResourcePair();
DataProviderRscData resourceData = new DataProviderRscData();
resourceData.setSessionId(session.getSessionId());
resource.setResourceData(resourceData);
resource.setProperties(new ResourceProperties());
resource.setLoadProperties(new LoadProperties());
resources.add(resource);
return resources;
}
private void sendSharedResource(ResourcePair rp, boolean remove) {
// Send event to venue to load resource
SharedResource sr = new SharedResource();
@ -358,29 +370,20 @@ public class DataProviderEventController extends AbstractRoleEventController {
@Override
public void shutdown() {
super.shutdown();
super.deactivateTelestrator();
SessionContainer sc = SharedDisplaySessionMgr
.getSessionContainer(session.getSessionId());
if (sc != null) {
for (IDisplayPaneContainer container : sc.getSharedEditors()) {
for (IDisplayPane pane : container.getDisplayPanes()) {
for (AbstractEditor editor : sc.getSharedEditors()) {
super.deactivateResources(editor);
for (IDisplayPane pane : editor.getDisplayPanes()) {
ResourceList list = pane.getDescriptor().getResourceList();
List<ResourcePair> rscToRemoveList = new ArrayList<ResourcePair>();
for (ResourcePair rp : list) {
unwrapResourcePair(rp);
if (rp.getResource() instanceof DataProviderRsc
|| rp.getResource() instanceof CollaborationDrawingLayer) {
rscToRemoveList.add(rp);
}
}
list.removePreAddListener(wrappingListener);
list.removePostRemoveListener(wrappingListener);
for (ResourcePair remove : rscToRemoveList) {
list.remove(remove);
}
}
DispatchingGraphicsFactory
.extractRemoteFunctionality(container);
DispatchingGraphicsFactory.extractRemoteFunctionality(editor);
}
}

View file

@ -106,9 +106,10 @@ public class ParticipantEventController extends AbstractRoleEventController {
}
initializeResources(editor.getActiveDisplayPane()
.getDescriptor());
activateResources(editor);
}
});
super.activateTelestrator(); // TODO should this be elsewhere?
}
@Subscribe
@ -191,7 +192,11 @@ public class ParticipantEventController extends AbstractRoleEventController {
@Override
public void shutdown() {
super.shutdown();
super.deactivateTelestrator(); // TODO should this be here?
SessionContainer container = SharedDisplaySessionMgr
.getSessionContainer(session.getSessionId());
if (container != null) {
super.deactivateResources(container.getCollaborationEditor());
}
if (this.collabRsc != null) {
this.session.unRegisterEventHandler(collabRsc);
}

View file

@ -24,6 +24,9 @@ import org.opengis.referencing.crs.CoordinateReferenceSystem;
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.ISharedDisplaySession;
import com.raytheon.uf.viz.collaboration.comm.identity.info.IVenueInfo;
import com.raytheon.uf.viz.collaboration.data.SessionContainer;
import com.raytheon.uf.viz.collaboration.data.SharedDisplaySessionMgr;
import com.raytheon.uf.viz.collaboration.display.editor.ReprojectEditor;
import com.raytheon.uf.viz.collaboration.ui.Activator;
import com.raytheon.uf.viz.core.IGraphicsTarget;
@ -31,7 +34,6 @@ import com.raytheon.uf.viz.core.drawables.IDescriptor;
import com.raytheon.uf.viz.core.drawables.PaintProperties;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.GenericResourceData;
import com.raytheon.uf.viz.core.rsc.LoadProperties;
/**
@ -54,17 +56,29 @@ import com.raytheon.uf.viz.core.rsc.LoadProperties;
*/
public class DataProviderRsc extends
AbstractVizResource<GenericResourceData, IDescriptor> {
AbstractVizResource<DataProviderRscData, IDescriptor> {
protected String roomName;
private String roomName;
protected String subject;
private String subject;
protected ISharedDisplaySession session;
private ISharedDisplaySession session;
public DataProviderRsc(GenericResourceData resourceData,
public DataProviderRsc(DataProviderRscData resourceData,
LoadProperties loadProperties) {
super(resourceData, loadProperties);
SessionContainer container = SharedDisplaySessionMgr
.getSessionContainer(resourceData.getSessionId());
if (container != null) {
session = container.getSession();
IVenueInfo info = session.getVenue().getInfo();
roomName = info.getVenueDescription();
subject = info.getVenueDescription();
}
}
public DataProviderRsc(DataProviderRsc rsc) {
this(rsc.getResourceData(), rsc.getLoadProperties());
}
@Override
@ -124,4 +138,15 @@ public class DataProviderRsc extends
this.session = session;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.core.rsc.AbstractVizResource#okToUnload()
*/
@Override
public boolean okToUnload() {
// Though I hate this methods exists, it serves its purpose
return false;
}
}

View file

@ -17,19 +17,19 @@
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.collaboration.ui.telestrator;
package com.raytheon.uf.viz.collaboration.ui.rsc;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import com.raytheon.uf.viz.core.drawables.IDescriptor;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.rsc.AbstractResourceData;
import com.raytheon.uf.viz.core.rsc.LoadProperties;
import com.raytheon.uf.viz.drawing.DrawingLayer;
import com.raytheon.uf.viz.drawing.PathDrawingResourceData;
/**
* Extends PathDrawingResourceData and holds the session id
* Resource data for the dataprovider resource
*
* <pre>
*
@ -37,58 +37,38 @@ import com.raytheon.uf.viz.drawing.PathDrawingResourceData;
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 3, 2012 mnash Initial creation
* May 25, 2012 mschenke Initial creation
*
* </pre>
*
* @author mnash
* @author mschenke
* @version 1.0
*/
@XmlAccessorType(XmlAccessType.NONE)
public class CollaborationPathDrawingResourceData extends
PathDrawingResourceData {
public class DataProviderRscData extends AbstractResourceData {
@XmlAttribute
private String sessionId;
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.drawing.PathDrawingResourceData#construct(com.raytheon
* com.raytheon.uf.viz.core.rsc.AbstractResourceData#construct(com.raytheon
* .uf.viz.core.rsc.LoadProperties,
* com.raytheon.uf.viz.core.drawables.IDescriptor)
*/
@Override
public DrawingLayer construct(LoadProperties loadProperties,
public DataProviderRsc construct(LoadProperties loadProperties,
IDescriptor descriptor) throws VizException {
CollaborationDrawingLayer layer = new CollaborationDrawingLayer(this,
loadProperties);
layer.initSession(sessionId);
return layer;
return new DataProviderRsc(this, loadProperties);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.viz.awipstools.ui.display.AwipsToolsResourceData#setClassT
* (java.lang.String)
/**
* @return the sessionId
*/
@Override
public String getClassT() {
return this.getClass().getCanonicalName();
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.viz.awipstools.ui.display.AwipsToolsResourceData#setClassT
* (java.lang.String)
*/
@Override
public void setClassT(String classT) {
public String getSessionId() {
return sessionId;
}
/**
@ -99,10 +79,32 @@ public class CollaborationPathDrawingResourceData extends
this.sessionId = sessionId;
}
/**
* @return the sessionId
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.rsc.AbstractResourceData#update(java.lang.Object
* )
*/
public String getSessionId() {
return sessionId;
@Override
public void update(Object updateData) {
}
/*
* (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 (getClass() != obj.getClass())
return false;
return true;
}
}

View file

@ -1,558 +0,0 @@
/**
* 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.telestrator;
import java.util.Collection;
import java.util.Iterator;
import org.eclipse.swt.graphics.RGB;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
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.viz.collaboration.comm.identity.CollaborationException;
import com.raytheon.uf.viz.collaboration.comm.identity.event.IVenueParticipantEvent;
import com.raytheon.uf.viz.collaboration.comm.identity.event.ParticipantEventType;
import com.raytheon.uf.viz.collaboration.comm.provider.user.UserId;
import com.raytheon.uf.viz.collaboration.data.CollaborationDataManager;
import com.raytheon.uf.viz.collaboration.data.SharedDisplaySessionMgr;
import com.raytheon.uf.viz.collaboration.ui.ColorChangeEvent;
import com.raytheon.uf.viz.collaboration.ui.SessionColorManager;
import com.raytheon.uf.viz.collaboration.ui.telestrator.event.CollaborationDrawingEvent;
import com.raytheon.uf.viz.collaboration.ui.telestrator.event.CollaborationDrawingEvent.CollaborationEventType;
import com.raytheon.uf.viz.core.IGraphicsTarget;
import com.raytheon.uf.viz.core.drawables.IWireframeShape;
import com.raytheon.uf.viz.core.drawables.PaintProperties;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.rsc.LoadProperties;
import com.raytheon.uf.viz.core.rsc.capabilities.ColorableCapability;
import com.raytheon.uf.viz.core.rsc.capabilities.ImagingCapability;
import com.raytheon.uf.viz.core.rsc.capabilities.OutlineCapability;
import com.raytheon.uf.viz.drawing.DrawingLayer;
import com.raytheon.uf.viz.drawing.PathDrawingResourceData;
import com.raytheon.uf.viz.remote.graphics.DispatchGraphicsTarget;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.TopologyException;
/**
* A layer that extends Drawing Layer but allows other users to have things
* drawn as well
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 3, 2012 mnash Initial creation
*
* </pre>
*
* @author mnash
* @version 1.0
*/
public class CollaborationDrawingLayer extends DrawingLayer {
protected static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(CollaborationDrawingLayer.class);
private Multimap<UserId, ShapeContainer> collaboratorShapes;
private Multimap<UserId, ShapeContainer> deletedCollaboratorShapes;
private String sessionId;
private UserId userId;
private SessionColorManager colorManager;
private IWireframeShape tempRemoteShape = null;
private boolean allowDraw = false;
/**
* @param data
* @param props
*/
public CollaborationDrawingLayer(PathDrawingResourceData data,
LoadProperties props) {
super(data, props);
CollaborationDataManager mgr = CollaborationDataManager.getInstance();
userId = mgr.getCollaborationConnection(true).getUser();
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.drawing.DrawingLayer#initInternal(com.raytheon.uf
* .viz.core.IGraphicsTarget)
*/
@Override
protected void initInternal(IGraphicsTarget target) throws VizException {
if (target instanceof DispatchGraphicsTarget) {
// Ensure we paint to our own target only
target = ((DispatchGraphicsTarget) target).getWrappedObject();
}
super.initInternal(target);
this.collaboratorShapes = LinkedHashMultimap.create();
this.collaboratorShapes = Multimaps
.synchronizedMultimap(this.collaboratorShapes);
this.deletedCollaboratorShapes = LinkedHashMultimap.create();
this.deletedCollaboratorShapes = Multimaps
.synchronizedMultimap(this.deletedCollaboratorShapes);
colorManager = SharedDisplaySessionMgr.getSessionContainer(sessionId)
.getColorManager();
color = colorManager.getColors().get(userId);
if (color != null) {
getCapability(ColorableCapability.class).setColor(color);
}
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.drawing.DrawingLayer#paintInternal(com.raytheon.uf
* .viz.core.IGraphicsTarget,
* com.raytheon.uf.viz.core.drawables.PaintProperties)
*/
@Override
protected void paintInternal(IGraphicsTarget target,
PaintProperties paintProps) throws VizException {
OutlineCapability outline = getCapability(OutlineCapability.class);
getCapability(ColorableCapability.class).setSuppressingMenuItems(true);
outline.setSuppressingMenuItems(true);
outline.setOutlineWidth(4);
ImagingCapability imaging = getCapability(ImagingCapability.class);
imaging.setSuppressingMenuItems(true);
if (target instanceof DispatchGraphicsTarget) {
// Ensure we paint to our own target only
target = ((DispatchGraphicsTarget) target).getWrappedObject();
}
super.paintInternal(target, paintProps);
// paint the shapes that come over from others
synchronized (collaboratorShapes) {
for (UserId userName : collaboratorShapes.keySet()) {
for (ShapeContainer sh : collaboratorShapes.get(userName)) {
if (sh != null) {
RGB col = colorManager.getColors().get(userName);
if (sh.getShape() != null && col != null) {
target.drawWireframeShape(sh.getShape(), col,
outline.getOutlineWidth(),
outline.getLineStyle(), imaging.getAlpha());
}
}
}
}
}
}
@Subscribe
public void setColorEvent(ColorChangeEvent event) {
this.color = event.getColor();
if (event.getUserName().equals(userId)) {
getCapability(ColorableCapability.class).setColor(this.color);
}
colorManager.getColorFromUser(event.getUserName());
issueRefresh();
}
@Subscribe
public void participantChanged(IVenueParticipantEvent event) {
if (event.getEventType().equals(ParticipantEventType.DEPARTED)) {
System.out
.println(event.getParticipant().getFQName() + " departed");
resetTemp();
clearSelfShapes(event.getParticipant());
issueRefresh();
}
}
@Subscribe
public void handle(CollaborationDrawingEvent event) {
switch (event.getType()) {
case DRAW:
addCollaborationShape(event.getUserName(), event.getContainer());
break;
case DISABLE:
allowDraw = !allowDraw;
getEventBus().post(event);
break;
case UNDO:
UserId userName = event.getUserName();
Collection<ShapeContainer> container = collaboratorShapes
.get(userName);
Iterator<ShapeContainer> itr = container.iterator();
ShapeContainer lastElement = null;
if (itr.hasNext()) {
lastElement = itr.next();
}
while (itr.hasNext()) {
lastElement = itr.next();
}
synchronized (deletedCollaboratorShapes) {
deletedCollaboratorShapes.put(userName, lastElement);
}
synchronized (collaboratorShapes) {
collaboratorShapes.get(userName).remove(lastElement);
}
break;
case REDO:
userName = event.getUserName();
container = deletedCollaboratorShapes.get(userName);
itr = container.iterator();
lastElement = null;
if (itr.hasNext()) {
lastElement = itr.next();
}
while (itr.hasNext()) {
lastElement = itr.next();
}
synchronized (collaboratorShapes) {
collaboratorShapes.put(userName, lastElement);
}
synchronized (deletedCollaboratorShapes) {
deletedCollaboratorShapes.get(userName).remove(lastElement);
}
break;
case CLEAR:
resetTemp();
clearSelfShapes(event.getUserName());
break;
case ERASE:
// TODO need to functionize this as it is mostly the same as
// DrawingLayer
userName = event.getUserName();
double extentPercentageX = paintProps.getView().getExtent()
.getWidth()
/ (double) paintProps.getCanvasBounds().width;
double cursorSize = 16;
double size = extentPercentageX * cursorSize;
Multimap<UserId, ShapeContainer> containers = HashMultimap.create();
synchronized (collaboratorShapes) {
for (ShapeContainer cont : collaboratorShapes.get(userName)) {
Geometry line = event.getContainer().getGeom();
if (line.buffer(size / 2).intersects(cont.getGeom())) {
Geometry intersection = line.buffer(size / 2)
.intersection(cont.getGeom());
Geometry finalGeom = null;
try {
finalGeom = cont.getGeom().difference(intersection);
} catch (TopologyException e) {
continue;
}
Geometry lString = null;
if (finalGeom instanceof MultiLineString) {
lString = (MultiLineString) finalGeom;
for (int j = 0; j < lString.getNumGeometries(); j++) {
LineString lineString = (LineString) lString
.getGeometryN(j);
eraseWireframeShape = target
.createWireframeShape(true, descriptor);
drawTempLinePrimitive(lineString,
eraseWireframeShape);
ShapeContainer shCont = new ShapeContainer();
shCont.setGeom(lString);
shCont.setShape(eraseWireframeShape);
containers.put(userName, shCont);
}
} else if (finalGeom instanceof LineString) {
GeometryFactory factory = new GeometryFactory();
lString = (LineString) finalGeom;
Point point = factory.createPoint(lString
.getCoordinates()[0]);
intersection = point.buffer(size / 2).intersection(
cont.getGeom());
finalGeom = cont.getGeom().difference(intersection);
eraseWireframeShape = target.createWireframeShape(
true, descriptor);
drawTempLinePrimitive(lString, eraseWireframeShape);
ShapeContainer shCont = new ShapeContainer();
shCont.setGeom(lString);
shCont.setShape(eraseWireframeShape);
containers.put(userName, shCont);
} else {
containers.put(userName, cont);
}
} else {
containers.put(userName, cont);
}
}
collaboratorShapes.clear();
collaboratorShapes.putAll(containers);
}
break;
}
issueRefresh();
}
/**
* @param userName
*/
private void clearSelfShapes(UserId userName) {
// TODO, does this need to clear all shapes if you are the session
// leader, or should it still just clear your own shapes
Multimap<UserId, ShapeContainer> map = LinkedHashMultimap
.create(collaboratorShapes);
for (UserId cont : map.keySet()) {
if (cont.equals(userName)) {
for (ShapeContainer shape : map.get(cont)) {
shape.getShape().dispose();
}
synchronized (collaboratorShapes) {
collaboratorShapes.removeAll(cont);
}
}
}
// this is what i was thinking of for clearing all shapes
// for (ShapeContainer cont : collaboratorShapes.get(userName)) {
// cont.getShape().dispose();
// }
synchronized (collaboratorShapes) {
collaboratorShapes.removeAll(userName);
}
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.drawing.DrawingLayer#addTempDrawLine(com.vividsolutions
* .jts.geom.LineString)
*/
@Override
public void addTempDrawLine(LineString line) {
super.addTempDrawLine(line);
// for showing the line on the fly...
// sendDrawEvent(line);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.drawing.DrawingLayer#addTempEraseLine(com.vividsolutions
* .jts.geom.LineString)
*/
@Override
public void addTempEraseLine(LineString line) {
super.addTempEraseLine(line);
// for erasing the line on the fly...
// sendEraseEvent(line);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.drawing.DrawingLayer#finalizeLine(com.vividsolutions
* .jts.geom.LineString, java.lang.String)
*/
@Override
public void finalizeLine(LineString line, String uuid) {
super.finalizeLine(line, uuid);
// for showing the line only after the artist lets up on the mouse
if (state == LayerState.DRAWING) {
sendDrawEvent(line);
} else if (state == LayerState.ERASING) {
sendEraseEvent(line);
}
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.drawing.DrawingLayer#undoAdd()
*/
@Override
public void undoAdd() {
super.undoAdd();
CollaborationDrawingEvent event = new CollaborationDrawingEvent();
event.setType(CollaborationEventType.UNDO);
event.setUserName(userId);
sendGenericEvent(event);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.drawing.DrawingLayer#redoAdd()
*/
@Override
public void redoAdd() {
super.redoAdd();
CollaborationDrawingEvent event = new CollaborationDrawingEvent();
event.setType(CollaborationEventType.REDO);
event.setUserName(userId);
sendGenericEvent(event);
}
public void sendDisableOthers() {
CollaborationDrawingEvent event = new CollaborationDrawingEvent();
event.setType(CollaborationEventType.DISABLE);
event.setUserName(userId);
sendGenericEvent(event);
}
private void sendEraseEvent(LineString line) {
ShapeContainer container = new ShapeContainer();
container.setGeom(line);
CollaborationDrawingEvent eObject = new CollaborationDrawingEvent();
eObject.setType(CollaborationEventType.ERASE);
eObject.setContainer(container);
eObject.setUserName(userId);
sendGenericEvent(eObject);
}
private void sendDrawEvent(LineString line) {
ShapeContainer container = new ShapeContainer();
container.setGeom(line);
CollaborationDrawingEvent tObject = new CollaborationDrawingEvent();
tObject.setType(CollaborationEventType.DRAW);
tObject.setContainer(container);
tObject.setUserName(userId);
sendGenericEvent(tObject);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.drawing.DrawingLayer#reset()
*/
@Override
public void reset() {
super.reset();
CollaborationDrawingEvent event = new CollaborationDrawingEvent();
event.setType(CollaborationEventType.CLEAR);
event.setUserName(userId);
sendGenericEvent(event);
}
private void sendGenericEvent(CollaborationDrawingEvent event) {
try {
SharedDisplaySessionMgr.getSessionContainer(sessionId).getSession()
.sendObjectToVenue(event);
} catch (CollaborationException e) {
statusHandler.handle(Priority.ERROR, "Unable to send event", e);
}
}
public void addCollaborationShape(UserId userName, ShapeContainer container) {
// if (tempRemoteShape == null){
tempRemoteShape = target.createWireframeShape(false, getDescriptor());
// }
drawTempLinePrimitive(container.getGeom(), tempRemoteShape);
container.setShape(tempRemoteShape);
synchronized (collaboratorShapes) {
collaboratorShapes.put(userName, container);
}
}
public void removeCollaborationShape(Geometry geom, RGB color) {
// synchronized (collaboratorShapes) {
// deletedCollaboratorShapes.
// collaboratorShapes.remove(geom, color);
// }
}
public void initSession(String sessionId) {
setSessionId(sessionId);
SharedDisplaySessionMgr.getSessionContainer(sessionId).getSession()
.registerEventHandler(this);
}
/**
* @return the allowDraw
*/
public boolean isAllowDraw() {
return allowDraw;
}
/**
* @param sessionId
* the sessionId to set
*/
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.drawing.DrawingLayer#disposeInternal()
*/
@Override
protected void disposeInternal() {
super.disposeInternal();
if (SharedDisplaySessionMgr.getSessionContainer(sessionId) != null
&& SharedDisplaySessionMgr.getSessionContainer(sessionId)
.getSession() != null) {
SharedDisplaySessionMgr.getSessionContainer(sessionId).getSession()
.unRegisterEventHandler(this);
}
// TODO, for disposing of all shapes (if the session leader)
// if (/* is session leader */false) {
// // synchronized (collaboratorShapes) {
// // for (IWireframeShape shape : collaboratorShapes.values()) {
// // shape.dispose();
// // }
// // }
//
// for (ShapeContainer cont : collaboratorShapes.values()) {
// cont.getShape().dispose();
// }
//
// for (ShapeContainer cont : deletedCollaboratorShapes.values()) {
// cont.getShape().dispose();
// }
//
// collaboratorShapes.clear();
// deletedCollaboratorShapes.clear();
// }
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.drawing.DrawingLayer#project(org.opengis.referencing
* .crs.CoordinateReferenceSystem)
*/
@Override
public void project(CoordinateReferenceSystem crs) throws VizException {
super.project(crs);
}
}

View file

@ -0,0 +1,363 @@
/**
* 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.telestrator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.google.common.eventbus.Subscribe;
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.event.IVenueParticipantEvent;
import com.raytheon.uf.viz.collaboration.comm.provider.user.UserId;
import com.raytheon.uf.viz.collaboration.data.SessionContainer;
import com.raytheon.uf.viz.collaboration.data.SharedDisplaySessionMgr;
import com.raytheon.uf.viz.collaboration.ui.Activator;
import com.raytheon.uf.viz.collaboration.ui.telestrator.event.CollaborationDrawingEvent;
import com.raytheon.uf.viz.collaboration.ui.telestrator.event.CollaborationDrawingEvent.CollaborationEventType;
import com.raytheon.uf.viz.core.IGraphicsTarget;
import com.raytheon.uf.viz.core.IGraphicsTarget.LineStyle;
import com.raytheon.uf.viz.core.drawables.IDescriptor;
import com.raytheon.uf.viz.core.drawables.IRenderableDisplay;
import com.raytheon.uf.viz.core.drawables.PaintProperties;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.LoadProperties;
import com.raytheon.uf.viz.core.rsc.capabilities.EditableCapability;
import com.raytheon.uf.viz.core.rsc.capabilities.OutlineCapability;
import com.raytheon.uf.viz.drawing.DrawingToolLayer;
import com.raytheon.uf.viz.drawing.DrawingToolLayer.DrawMode;
import com.raytheon.uf.viz.remote.graphics.DispatchGraphicsTarget;
import com.raytheon.viz.ui.input.EditableManager;
import com.vividsolutions.jts.geom.Coordinate;
/**
* Resource that uses DrawingToolLayer to render drawn data for multiple users
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* May 23, 2012 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class CollaborationDrawingResource extends
AbstractVizResource<CollaborationDrawingResourceData, IDescriptor> {
private SessionContainer container;
private UserId myUser;
private Map<UserId, DrawingToolLayer> layerMap;
private CollaborationDrawingUIManager manager;
private boolean lockingDrawing = false;
/**
* @param resourceData
* @param loadProperties
*/
public CollaborationDrawingResource(
CollaborationDrawingResourceData resourceData,
LoadProperties loadProperties) {
super(resourceData, loadProperties);
}
public CollaborationDrawingResource(CollaborationDrawingResource resource) {
super(resource.getResourceData(), resource.getLoadProperties());
this.layerMap = new HashMap<UserId, DrawingToolLayer>(resource.layerMap);
resource.layerMap.clear();
this.myUser = resource.myUser;
this.getCapabilities().addCapability(
resource.getCapability(OutlineCapability.class));
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.rsc.AbstractVizResource#initInternal(com.raytheon
* .uf.viz.core.IGraphicsTarget)
*/
@Override
protected void initInternal(IGraphicsTarget target) throws VizException {
EditableManager.makeEditable(this, true);
container = SharedDisplaySessionMgr.getSessionContainer(resourceData
.getSessionId());
if (container == null) {
throw new VizException("Could not find container for sessionId: "
+ resourceData.getSessionId());
}
if (layerMap == null) {
// Don't reinitialized
myUser = container.getSession().getUserID();
layerMap = new HashMap<UserId, DrawingToolLayer>();
OutlineCapability outline = getCapability(OutlineCapability.class);
outline.setLineStyle(LineStyle.SOLID);
outline.setOutlineWidth(4);
outline.setSuppressingMenuItems(true);
}
manager = new CollaborationDrawingUIManager(this);
container.getSession().registerEventHandler(this);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.rsc.AbstractVizResource#paintInternal(com.raytheon
* .uf.viz.core.IGraphicsTarget,
* com.raytheon.uf.viz.core.drawables.PaintProperties)
*/
@Override
protected void paintInternal(IGraphicsTarget target,
PaintProperties paintProps) throws VizException {
if (target instanceof DispatchGraphicsTarget) {
// Ensure we paint to our own target only
target = ((DispatchGraphicsTarget) target).getWrappedObject();
}
OutlineCapability outline = getCapability(OutlineCapability.class);
synchronized (layerMap) {
for (UserId user : layerMap.keySet()) {
DrawingToolLayer layer = layerMap.get(user);
if (layer != null) {
layer.setEraserWidth(16); // Configure?
layer.setLineStyle(outline.getLineStyle());
layer.setLineWidth(outline.getOutlineWidth());
layer.setColor(container.getColorManager()
.getColorFromUser(user));
layer.paint(target, paintProps);
}
}
}
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.core.rsc.AbstractVizResource#disposeInternal()
*/
@Override
protected void disposeInternal() {
for (DrawingToolLayer layer : layerMap.values()) {
layer.dispose();
}
layerMap.clear();
layerMap = null;
manager.dispose();
container.getSession().unRegisterEventHandler(this);
}
/**
* @return the myUser
*/
public UserId getMyUser() {
return myUser;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.core.rsc.IVizResource#getName()
*/
public String getName() {
return "Telestrator Drawing Tool";
}
/**
* Get the DrawingToolLayer object associated with the user, one will be
* created if none exists
*
* @param user
* @return
*/
public DrawingToolLayer getDrawingLayerFor(UserId user) {
synchronized (layerMap) {
DrawingToolLayer layer = layerMap.get(user);
if (layer == null) {
if (user == myUser) {
layer = new CollaborationDrawingToolLayer(
descriptor.getGridGeometry(), this);
} else {
layer = new DrawingToolLayer(descriptor.getGridGeometry());
}
layerMap.put(user, layer);
}
return layer;
}
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.rsc.AbstractVizResource#project(org.opengis.
* referencing.crs.CoordinateReferenceSystem)
*/
@Override
public void project(CoordinateReferenceSystem crs) throws VizException {
synchronized (layerMap) {
for (DrawingToolLayer layer : layerMap.values()) {
layer.reproject(descriptor.getGridGeometry());
}
}
}
/**
* @return
*/
public boolean isSessionLeader() {
return container.getSession().getCurrentSessionLeader().equals(myUser);
}
/**
* @return
*/
public boolean isLockingDrawing() {
return lockingDrawing;
}
public void setLockingDrawing(boolean lockingDrawing) {
this.lockingDrawing = lockingDrawing;
if (isSessionLeader()) {
CollaborationDrawingEvent event = new CollaborationDrawingEvent();
event.setUserName(myUser);
event.setType(CollaborationEventType.TOGGLE_LOCK);
sendEvent(event);
}
}
/**
* Checks if this resource is able to tellestrate given its state
*
* @return
*/
public boolean canTellestrate() {
return getCapability(EditableCapability.class).isEditable()
&& (isSessionLeader() || isLockingDrawing() == false);
}
@Subscribe
public void participantChanged(IVenueParticipantEvent event) {
UserId user = event.getParticipant();
switch (event.getEventType()) {
case DEPARTED:
synchronized (layerMap) {
DrawingToolLayer layer = layerMap.remove(user);
if (layer != null) {
layer.dispose();
issueRefresh();
}
}
break;
case ARRIVED:
// TODO: Send all your user data?
break;
}
}
@Subscribe
public void handleDrawEvent(CollaborationDrawingEvent event) {
UserId user = event.getUserName();
if (user.equals(myUser)) {
// Early exit case, don't process my own events twice
return;
}
synchronized (layerMap) {
DrawingToolLayer layer = getDrawingLayerFor(user);
List<Coordinate> points = event.getCoordinates();
switch (event.getType()) {
case CLEAR:
layer.clear();
break;
case TOGGLE_LOCK:
// Toggle locking
setLockingDrawing(!isLockingDrawing());
break;
case DRAW:
layer.setDrawMode(DrawMode.DRAW);
if (points != null) {
for (Coordinate c : points) {
layer.addCoordinate(c);
}
}
layer.doneDrawing();
break;
case ERASE:
layer.setDrawMode(DrawMode.ERASE);
if (points != null) {
for (Coordinate c : points) {
layer.addCoordinate(c);
}
}
layer.doneErasing();
IRenderableDisplay display = descriptor.getRenderableDisplay();
layer.processErase(display.getExtent(), display.getBounds());
break;
case REDO:
layer.redo();
break;
case UNDO:
layer.undo();
break;
}
}
issueRefresh();
}
public void sendEvent(Object event) {
try {
container.getSession().sendObjectToVenue(event);
} catch (CollaborationException e) {
Activator.statusHandler.handle(Priority.PROBLEM,
e.getLocalizedMessage(), e);
}
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.core.rsc.AbstractVizResource#okToUnload()
*/
@Override
public boolean okToUnload() {
// Though I hate this methods exists, it serves its purpose
return false;
}
}

View file

@ -17,18 +17,19 @@
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.drawing;
package com.raytheon.uf.viz.collaboration.ui.telestrator;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import com.raytheon.uf.viz.core.drawables.IDescriptor;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.rsc.AbstractResourceData;
import com.raytheon.uf.viz.core.rsc.LoadProperties;
import com.raytheon.viz.awipstools.ui.display.AwipsToolsResourceData;
/**
* The resource data for the path drawing layer
* Resource data for the CollaborationDrawingResource
*
* <pre>
*
@ -36,53 +37,75 @@ import com.raytheon.viz.awipstools.ui.display.AwipsToolsResourceData;
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 22, 2012 mnash Initial creation
* May 23, 2012 mschenke Initial creation
*
* </pre>
*
* @author mnash
* @author mschenke
* @version 1.0
*/
@XmlAccessorType(XmlAccessType.NONE)
public class PathDrawingResourceData extends
AwipsToolsResourceData<DrawingLayer> {
public class CollaborationDrawingResourceData extends AbstractResourceData {
@XmlAttribute
private String sessionId;
/*
* (non-Javadoc)
*
* @see
* com.raytheon.viz.awipstools.ui.display.AwipsToolsResourceData#construct
* (com.raytheon.uf.viz.core.rsc.LoadProperties,
* com.raytheon.uf.viz.core.rsc.AbstractResourceData#construct(com.raytheon
* .uf.viz.core.rsc.LoadProperties,
* com.raytheon.uf.viz.core.drawables.IDescriptor)
*/
@Override
public DrawingLayer construct(LoadProperties loadProperties,
IDescriptor descriptor) throws VizException {
DrawingLayer layer = new DrawingLayer(this, loadProperties);
return layer;
public CollaborationDrawingResource construct(
LoadProperties loadProperties, IDescriptor descriptor)
throws VizException {
return new CollaborationDrawingResource(this, loadProperties);
}
/**
* @return the sessionId
*/
public String getSessionId() {
return sessionId;
}
/**
* @param sessionId
* the sessionId to set
*/
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.viz.awipstools.ui.display.AwipsToolsResourceData#update(
* java.lang.Object)
* com.raytheon.uf.viz.core.rsc.AbstractResourceData#update(java.lang.Object
* )
*/
@Override
public void update(Object updateData) {
super.update(updateData);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.viz.awipstools.ui.display.AwipsToolsResourceData#getClassT()
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public String getClassT() {
return this.getClass().getCanonicalName();
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
return true;
}
}

View file

@ -0,0 +1,148 @@
/**
* 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.telestrator;
import java.util.ArrayList;
import java.util.List;
import org.geotools.coverage.grid.GeneralGridGeometry;
import com.raytheon.uf.viz.collaboration.ui.telestrator.event.CollaborationDrawingEvent;
import com.raytheon.uf.viz.collaboration.ui.telestrator.event.CollaborationDrawingEvent.CollaborationEventType;
import com.raytheon.uf.viz.drawing.DrawingToolLayer;
import com.vividsolutions.jts.geom.Coordinate;
/**
* Extension of DrawingToolLayer that forwards events for other participants to
* keep in sync
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* May 24, 2012 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class CollaborationDrawingToolLayer extends DrawingToolLayer {
private CollaborationDrawingResource resource;
private List<Coordinate> coordinates = new ArrayList<Coordinate>();
/**
* @param targetGeometry
*/
public CollaborationDrawingToolLayer(GeneralGridGeometry targetGeometry,
CollaborationDrawingResource resource) {
super(targetGeometry);
this.resource = resource;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.drawing.DrawingToolLayer#addCoordinate(com.vividsolutions
* .jts.geom.Coordinate)
*/
@Override
public void addCoordinate(Coordinate coord) {
super.addCoordinate(coord);
coordinates.add(coord);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.drawing.DrawingToolLayer#doneDrawing()
*/
@Override
public void doneDrawing() {
super.doneDrawing();
sendCoordinateEvent(CollaborationEventType.DRAW);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.drawing.DrawingToolLayer#doneErasing()
*/
@Override
public void doneErasing() {
super.doneErasing();
sendCoordinateEvent(CollaborationEventType.ERASE);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.drawing.DrawingToolLayer#undo()
*/
@Override
public void undo() {
super.undo();
sendSimpleEvent(CollaborationEventType.UNDO);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.drawing.DrawingToolLayer#redo()
*/
@Override
public void redo() {
super.redo();
sendSimpleEvent(CollaborationEventType.REDO);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.drawing.DrawingToolLayer#clear()
*/
@Override
public void clear() {
super.clear();
sendSimpleEvent(CollaborationEventType.CLEAR);
}
private void sendCoordinateEvent(CollaborationEventType type) {
CollaborationDrawingEvent event = new CollaborationDrawingEvent();
event.setType(type);
event.setUserName(resource.getMyUser());
event.setCoordinates(new ArrayList<Coordinate>(coordinates));
resource.sendEvent(event);
coordinates.clear();
}
private void sendSimpleEvent(CollaborationEventType type) {
CollaborationDrawingEvent event = new CollaborationDrawingEvent();
event.setType(type);
event.setUserName(resource.getMyUser());
resource.sendEvent(event);
}
}

View file

@ -0,0 +1,276 @@
/**
* 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.telestrator;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
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.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.IWorkbenchWindow;
import com.raytheon.uf.viz.collaboration.ui.Activator;
import com.raytheon.uf.viz.core.ContextManager;
import com.raytheon.uf.viz.core.IDisplayPane;
import com.raytheon.uf.viz.core.IDisplayPaneContainer;
import com.raytheon.uf.viz.core.IVizEditorChangedListener;
import com.raytheon.uf.viz.core.icon.IconUtil;
import com.raytheon.uf.viz.drawing.DrawingToolbar;
import com.raytheon.viz.ui.EditorUtil;
import com.raytheon.viz.ui.VizWorkbenchManager;
/**
* Collaboration drawing toolbar, adds locking of collaborators
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* May 23, 2012 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class CollaborationDrawingToolbar extends DrawingToolbar implements
IVizEditorChangedListener {
private static CollaborationDrawingToolbar instance;
private Set<CollaborationDrawingResource> resources = new HashSet<CollaborationDrawingResource>();
public static CollaborationDrawingToolbar openToolbar(
CollaborationDrawingResource resource) {
if (instance == null) {
instance = new CollaborationDrawingToolbar(VizWorkbenchManager
.getInstance().getCurrentWindow());
instance.open();
}
instance.resources.add(resource);
return instance;
}
/**
* Get the current instance of the toolbar, will not create if null
*
* @return
*/
public static CollaborationDrawingToolbar getInstance() {
return instance;
}
private ToolItem leaderOnly;
private List<CollaborationDrawingResource> activeEditorResources = new ArrayList<CollaborationDrawingResource>();
private IWorkbenchWindow window;
/**
* @param parentShell
*/
private CollaborationDrawingToolbar(IWorkbenchWindow window) {
super(window.getShell());
this.window = window;
setText("Collaboration Drawing");
VizWorkbenchManager.getInstance().addListener(this);
IDisplayPaneContainer active = EditorUtil.getActiveVizContainer(window);
if (active != null) {
editorChanged(active);
}
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.ui.dialogs.CaveSWTDialogBase#opened()
*/
@Override
protected void opened() {
super.opened();
ContextManager.getInstance(window).activateContexts(this);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.drawing.DrawingToolbar#addToolsToToolBar(org.eclipse
* .swt.widgets.ToolBar)
*/
@Override
protected void addToolsToToolBar(ToolBar toolbar) {
super.addToolsToToolBar(toolbar);
undoItem.setToolTipText("Ctrl+Z to Undo");
redoItem.setToolTipText("Ctrl+Y to Undo");
leaderOnly = new ToolItem(toolbar, SWT.CHECK);
leaderOnly.setText("Lock Collaborators");
leaderOnly.setImage(IconUtil.getImageDescriptor(
Activator.getDefault().getBundle(), "multiple_draw.gif")
.createImage());
leaderOnly.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
for (CollaborationDrawingResource resource : activeEditorResources) {
resource.setLockingDrawing(leaderOnly.getSelection());
}
}
});
}
/**
* Fuction for notifying the toolbar a resource has changed, will update the
* UI if the resource is currently being managed by the toolbar
*
* @param resource
*/
public void resourceChanged(CollaborationDrawingResource resource) {
if (activeEditorResources.contains(resource)) {
updateItemState();
}
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.drawing.DrawingToolbar#nullLayer()
*/
@Override
protected void nullLayer() {
super.nullLayer();
leaderOnly.setSelection(false);
leaderOnly.setEnabled(false);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.drawing.DrawingToolbar#validLayer()
*/
@Override
protected void validLayer() {
super.validLayer();
for (CollaborationDrawingResource resource : activeEditorResources) {
leaderOnly.setEnabled(resource.isSessionLeader());
leaderOnly.setSelection(resource.isLockingDrawing());
break;
}
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.ui.dialogs.CaveSWTDialogBase#disposed()
*/
@Override
protected void disposed() {
super.disposed();
resources.clear();
VizWorkbenchManager.getInstance().removeListener(this);
ContextManager.getInstance(window).deactivateContexts(this);
}
/**
* Function for notifying the toolbar a resource has been disposed, toolbar
* will close when no resources are left being managed
*
* @param resource
*/
public synchronized void disposed(CollaborationDrawingResource resource) {
resources.remove(resource);
activeEditorResources.remove(resource);
if (resources.size() == 0) {
close();
instance = null;
}
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.IVizEditorChangedListener#editorChanged(com.
* raytheon.uf.viz.core.IDisplayPaneContainer)
*/
@Override
public void editorChanged(IDisplayPaneContainer container) {
List<CollaborationDrawingResource> activeResources = new ArrayList<CollaborationDrawingResource>();
for (IDisplayPane pane : container.getDisplayPanes()) {
List<CollaborationDrawingResource> paneResources = pane
.getDescriptor()
.getResourceList()
.getResourcesByTypeAsType(
CollaborationDrawingResource.class);
activeResources.addAll(paneResources);
}
activeEditorResources = activeResources;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.drawing.DrawingToolbar#undo()
*/
@Override
public void undo() {
super.undo();
refresh();
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.drawing.DrawingToolbar#redo()
*/
@Override
public void redo() {
super.redo();
refresh();
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.drawing.DrawingToolbar#clear()
*/
@Override
protected void clear() {
super.clear();
refresh();
}
/**
* Refresh the resource to repaint
*/
private void refresh() {
for (CollaborationDrawingResource resource : activeEditorResources) {
resource.issueRefresh();
}
}
}

View file

@ -0,0 +1,108 @@
/**
* 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.telestrator;
import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.uf.viz.drawing.DrawingToolUIManager;
/**
* UI Manager for the CollaborationDrawingResource, handles mouse input and
* opens the toolbar
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* May 23, 2012 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class CollaborationDrawingUIManager extends DrawingToolUIManager {
private CollaborationDrawingResource resource;
private CollaborationDrawingToolbar toolbar;
public CollaborationDrawingUIManager(CollaborationDrawingResource resource) {
super(resource.getDrawingLayerFor(resource.getMyUser()), resource
.getResourceContainer());
this.resource = resource;
VizApp.runAsync(new Runnable() {
@Override
public void run() {
CollaborationDrawingResource resource = CollaborationDrawingUIManager.this.resource;
toolbar = CollaborationDrawingToolbar.openToolbar(resource);
toolbar.setCurrentDrawingLayer(resource
.getDrawingLayerFor(resource.getMyUser()));
}
});
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.drawing.DrawingToolUIManager#dispose()
*/
@Override
public void dispose() {
super.dispose();
if (toolbar != null) {
// Incase disposed before async exec can run in constructor
toolbar.disposed(resource);
}
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.drawing.DrawingToolUIManager#handleMouseDown(int,
* int, int)
*/
@Override
public boolean handleMouseDown(int x, int y, int mouseButton) {
if (resource.canTellestrate() == false) {
return false;
}
return super.handleMouseDown(x, y, mouseButton);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.drawing.DrawingToolUIManager#handleMouseUp(int,
* int, int)
*/
@Override
public boolean handleMouseUp(int x, int y, int mouseButton) {
boolean rval = super.handleMouseUp(x, y, mouseButton);
if (rval) {
toolbar.resourceChanged(resource);
}
return rval;
}
}

View file

@ -1,163 +0,0 @@
/**
* 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.telestrator;
import com.raytheon.uf.viz.collaboration.comm.identity.user.SharedDisplayRole;
import com.raytheon.uf.viz.collaboration.data.SharedDisplaySessionMgr;
import com.raytheon.uf.viz.core.rsc.AbstractResourceData;
import com.raytheon.uf.viz.core.rsc.IInputHandler;
import com.raytheon.uf.viz.drawing.tools.PathDrawingTool;
/**
* Extends the PathDrawingTool with logic to allow for locking of other users
* ("Leader Only") as well as holding the session id
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 3, 2012 mnash Initial creation
*
* </pre>
*
* @author mnash
* @version 1.0
*/
public class CollaborationPathDrawingTool extends PathDrawingTool {
private String session;
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.drawing.tools.PathDrawingTool#constructData()
*/
@Override
public AbstractResourceData constructData() {
CollaborationPathDrawingResourceData data = new CollaborationPathDrawingResourceData();
data.setSessionId(session);
return data;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.drawing.AbstractDrawingTool#activateTool()
*/
@Override
protected void activateTool() {
super.activateTool();
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.drawing.tools.PathDrawingTool#getMouseHandler()
*/
@Override
public IInputHandler getMouseHandler() {
if (theHandler == null) {
theHandler = new CollaborationPathDrawingHandler();
}
return theHandler;
}
public class CollaborationPathDrawingHandler extends PathDrawingHandler {
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.ui.input.IInputHandler#handleMouseDown(int,
* int, int)
*/
@Override
public boolean handleMouseDown(int anX, int aY, int button) {
if (theDrawingLayer == null) {
return false;
}
boolean allowDraw = ((CollaborationDrawingLayer) theDrawingLayer)
.isAllowDraw();
boolean isSessionLeader = SharedDisplaySessionMgr
.getSessionContainer(session).getSession()
.hasRole(SharedDisplayRole.SESSION_LEADER);
if (allowDraw && !isSessionLeader) {
return false;
}
return super.handleMouseDown(anX, aY, button);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.ui.input.IInputHandler#handleMouseDownMove(int,
* int, int)
*/
@Override
public boolean handleMouseDownMove(int x, int y, int button) {
boolean allowDraw = ((CollaborationDrawingLayer) theDrawingLayer)
.isAllowDraw();
boolean isSessionLeader = SharedDisplaySessionMgr
.getSessionContainer(session).getSession()
.hasRole(SharedDisplayRole.SESSION_LEADER);
if (allowDraw && !isSessionLeader) {
return false;
}
return super.handleMouseDownMove(x, y, button);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.ui.input.IInputHandler#handleMouseUp(int, int,
* int)
*/
@Override
public boolean handleMouseUp(int anX, int aY, int button) {
boolean allowDraw = ((CollaborationDrawingLayer) theDrawingLayer)
.isAllowDraw();
boolean isSessionLeader = SharedDisplaySessionMgr
.getSessionContainer(session).getSession()
.hasRole(SharedDisplayRole.SESSION_LEADER);
if (allowDraw && !isSessionLeader) {
return false;
}
return super.handleMouseUp(anX, aY, button);
}
}
/**
* @param session
* the session to set
*/
public void setSession(String session) {
this.session = session;
}
/**
* @return the session
*/
public String getSession() {
return session;
}
}

View file

@ -1,168 +0,0 @@
/**
* 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.telestrator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolItem;
import com.raytheon.uf.viz.collaboration.comm.identity.ISharedDisplaySession;
import com.raytheon.uf.viz.collaboration.comm.identity.user.SharedDisplayRole;
import com.raytheon.uf.viz.collaboration.data.CollaborationDataManager;
import com.raytheon.uf.viz.collaboration.data.SharedDisplaySessionMgr;
import com.raytheon.uf.viz.collaboration.ui.Activator;
import com.raytheon.uf.viz.collaboration.ui.telestrator.event.CollaborationDrawingEvent;
import com.raytheon.uf.viz.collaboration.ui.telestrator.event.CollaborationDrawingEvent.CollaborationEventType;
import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.uf.viz.core.icon.IconUtil;
import com.raytheon.uf.viz.drawing.DrawingLayer;
import com.raytheon.uf.viz.drawing.PathToolbar;
import com.raytheon.uf.viz.drawing.events.DrawingEvent;
import com.raytheon.uf.viz.drawing.events.DrawingEventBus;
/**
* Extends the toolbar and adds the "Leader Only" button
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 3, 2012 mnash Initial creation
*
* </pre>
*
* @author mnash
* @version 1.0
*/
public class CollaborationPathToolbar extends PathToolbar {
private ToolItem leaderOnly;
/**
* @param parentShell
*/
protected CollaborationPathToolbar(Shell parentShell) {
super(parentShell);
setText("Collaboration Drawing");
}
public static PathToolbar getToolbar() {
if (pathToolbar == null) {
pathToolbar = new CollaborationPathToolbar(new Shell(
Display.getCurrent()));
DrawingEventBus.register(PathToolbar.getToolbar());
}
return pathToolbar;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.drawing.PathToolbar#initializeComponents(org.eclipse
* .swt.widgets.Shell)
*/
@Override
protected void initializeComponents(Shell shell) {
// allows for subclasses to add more items to the toolbar, in this case
// allowing the user to turn off other collaborator drawings
super.initializeComponents(shell);
createLeaderItem();
}
@Override
public void handleMessage(final DrawingEvent event) {
VizApp.runAsync(new Runnable() {
@Override
public void run() {
if (event instanceof CollaborationDrawingEvent) {
CollaborationDrawingEvent cde = (CollaborationDrawingEvent) event;
if (!cde.getUserName()
.equals(CollaborationDataManager.getInstance()
.getCollaborationConnection(true).getUser())) {
if (cde.getType() == CollaborationEventType.DISABLE) {
disableAll();
}
}
}
CollaborationPathToolbar.super.handleMessage(event);
}
});
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.drawing.PathToolbar#updateToolbar()
*/
@Override
public void updateToolbar() {
super.updateToolbar();
// for non-leaders, need to disable/remove the leaderOnly button
DrawingLayer resource = getDrawingResource();
if (resource.getResourceData() instanceof CollaborationPathDrawingResourceData) {
String sessionId = ((CollaborationPathDrawingResourceData) resource
.getResourceData()).getSessionId();
ISharedDisplaySession session = SharedDisplaySessionMgr
.getSessionContainer(sessionId).getSession();
if (session != null
&& !session.hasRole(SharedDisplayRole.SESSION_LEADER)
&& leaderOnly != null && !leaderOnly.isDisposed()) {
leaderOnly.setEnabled(false);
}
}
}
private void createLeaderItem() {
leaderOnly = new ToolItem(toolbar, SWT.CHECK);
leaderOnly.setText("Lock Collaborators");
leaderOnly.setImage(IconUtil.getImageDescriptor(
Activator.getDefault().getBundle(), "multiple_draw.gif")
.createImage());
leaderOnly.setSelection(false);
leaderOnly.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
DrawingLayer layer = getDrawingResource();
if (layer instanceof CollaborationDrawingLayer) {
CollaborationDrawingLayer dLayer = (CollaborationDrawingLayer) layer;
dLayer.sendDisableOthers();
}
if (leaderOnly.getSelection()) {
lastTool.activate();
} else {
lastTool.deactivate();
}
}
});
}
public void disableAll() {
if (toolbar != null && !toolbar.isDisposed()) {
toolbar.setEnabled(!toolbar.getEnabled());
}
}
}

View file

@ -1,86 +0,0 @@
/**
* 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.telestrator;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
import com.raytheon.uf.viz.core.drawables.IWireframeShape;
import com.vividsolutions.jts.geom.Geometry;
/**
* This container holds the wireframe shape as well as the geometry that it
* applies to. This will get serialized and sent over the network to other
* users, and will just be the geometry at that time.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 4, 2012 mnash Initial creation
*
* </pre>
*
* @author mnash
* @version 1.0
*/
@DynamicSerialize
public class ShapeContainer {
private IWireframeShape shape;
@DynamicSerializeElement
private Geometry geom;
public ShapeContainer() {
}
/**
* @return the shape
*/
public IWireframeShape getShape() {
return shape;
}
/**
* @param shape
* the shape to set
*/
public void setShape(IWireframeShape shape) {
this.shape = shape;
}
/**
* @return the geom
*/
public Geometry getGeom() {
return geom;
}
/**
* @param geom
* the geom to set
*/
public void setGeom(Geometry geom) {
this.geom = geom;
}
}

View file

@ -19,11 +19,12 @@
**/
package com.raytheon.uf.viz.collaboration.ui.telestrator.event;
import java.util.List;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
import com.raytheon.uf.viz.collaboration.comm.provider.user.UserId;
import com.raytheon.uf.viz.collaboration.ui.telestrator.ShapeContainer;
import com.raytheon.uf.viz.drawing.events.DrawingEvent;
import com.vividsolutions.jts.geom.Coordinate;
/**
* TODO Add Description
@ -43,14 +44,14 @@ import com.raytheon.uf.viz.drawing.events.DrawingEvent;
*/
@DynamicSerialize
public class CollaborationDrawingEvent extends DrawingEvent {
public class CollaborationDrawingEvent {
public static enum CollaborationEventType {
DRAW, ERASE, REDO, UNDO, CLEAR, DISABLE;
DRAW, ERASE, REDO, UNDO, CLEAR, TOGGLE_LOCK;
}
@DynamicSerializeElement
private ShapeContainer container;
private List<Coordinate> coordinates;
@DynamicSerializeElement
private UserId userName;
@ -58,26 +59,19 @@ public class CollaborationDrawingEvent extends DrawingEvent {
@DynamicSerializeElement
private CollaborationEventType type;
public CollaborationDrawingEvent() {
}
public CollaborationDrawingEvent(ShapeContainer cont) {
this.container = cont;
/**
* @return the coordinates
*/
public List<Coordinate> getCoordinates() {
return coordinates;
}
/**
* @return the container
* @param coordinates
* the coordinates to set
*/
public ShapeContainer getContainer() {
return container;
}
/**
* @param container
* the container to set
*/
public void setContainer(ShapeContainer container) {
this.container = container;
public void setCoordinates(List<Coordinate> coordinates) {
this.coordinates = coordinates;
}
/**

View file

@ -17,21 +17,16 @@
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.drawing.actions;
package com.raytheon.uf.viz.collaboration.ui.telestrator.handlers;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import com.raytheon.uf.viz.core.drawables.ResourcePair;
import com.raytheon.uf.viz.core.rsc.ResourceList;
import com.raytheon.uf.viz.drawing.DrawingLayer;
import com.raytheon.uf.viz.drawing.events.DrawingEvent;
import com.raytheon.viz.ui.EditorUtil;
import com.raytheon.viz.ui.editor.AbstractEditor;
import com.raytheon.uf.viz.collaboration.ui.telestrator.CollaborationDrawingToolbar;
/**
* Removes the last shape that was drawn
* Action for invoking undo/redo on the CollaborationDrawingToolbar
*
* <pre>
*
@ -39,28 +34,42 @@ import com.raytheon.viz.ui.editor.AbstractEditor;
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 23, 2012 mnash Initial creation
* May 24, 2012 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class UndoAddAction extends AbstractHandler {
public class UndoRedoHandler extends AbstractHandler {
private static final String ACTION_ID = "com.raytheon.uf.viz.collaboration.tellestrator.action";
private static final String UNDO_ID = "UNDO";
private static final String REDO_ID = "REDO";
/*
* (non-Javadoc)
*
* @see
* org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.
* ExecutionEvent)
*/
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
ResourceList list = ((AbstractEditor) EditorUtil
.getActiveEditorAs(AbstractEditor.class))
.getActiveDisplayPane().getDescriptor().getResourceList();
for (ResourcePair pair : list) {
if (pair.getResource() instanceof DrawingLayer) {
((DrawingLayer) pair.getResource()).undoAdd();
((DrawingLayer) pair.getResource()).getEventBus().post(
new DrawingEvent());
break;
CollaborationDrawingToolbar toolbar = CollaborationDrawingToolbar
.getInstance();
if (toolbar != null) {
String action = event.getParameter(ACTION_ID);
if (UNDO_ID.equals(action)) {
toolbar.undo();
} else if (REDO_ID.equals(action)) {
toolbar.redo();
}
}
return null;
}
}

View file

@ -11,16 +11,11 @@ Require-Bundle: org.eclipse.ui,
com.raytheon.uf.viz.core;bundle-version="1.12.1174",
com.raytheon.uf.viz.core.rsc;bundle-version="1.0.0",
com.raytheon.uf.common.geospatial;bundle-version="1.12.1174",
com.raytheon.viz.awipstools;bundle-version="1.12.1174",
com.raytheon.viz.ui;bundle-version="1.12.1174",
com.google.guava;bundle-version="1.0.0",
org.geotools
org.geotools,
com.raytheon.viz.core;bundle-version="1.12.1174"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Import-Package: com.raytheon.uf.common.time,
com.raytheon.viz.ui.cmenu,
com.vividsolutions.jts.geom
Export-Package: com.raytheon.uf.viz.drawing,
com.raytheon.uf.viz.drawing.actions,
com.raytheon.uf.viz.drawing.events,
com.raytheon.uf.viz.drawing.tools
Export-Package: com.raytheon.uf.viz.drawing

View file

@ -20,68 +20,4 @@
-->
<?eclipse version="3.2"?>
<plugin>
<extension
point="org.eclipse.ui.commands">
<command
id="com.raytheon.uf.viz.drawing.undoadd"
name="Undo Add">
</command>
<command
id="com.raytheon.uf.viz.drawing.redoadd"
name="Redo Add">
</command>
</extension>
<extension
point="org.eclipse.ui.handlers">
<handler
class="com.raytheon.uf.viz.drawing.actions.UndoAddAction"
commandId="com.raytheon.uf.viz.drawing.undoadd">
</handler>
<handler
class="com.raytheon.uf.viz.drawing.actions.RedoAddAction"
commandId="com.raytheon.uf.viz.drawing.redoadd">
</handler>
</extension>
<extension
point="org.eclipse.ui.contexts">
<context
description="Drawing Context"
id="com.raytheon.uf.viz.drawing.context"
name="Drawing Context">
</context>
</extension>
<extension
point="org.eclipse.ui.bindings">
<key
commandId="com.raytheon.uf.viz.drawing.undoadd"
contextId="com.raytheon.uf.viz.drawing.context"
schemeId="com.raytheon.viz.ui.awips.scheme"
sequence="M1+Z">
</key>
<key
commandId="com.raytheon.uf.viz.drawing.redoadd"
contextId="com.raytheon.uf.viz.drawing.context"
schemeId="com.raytheon.viz.ui.awips.scheme"
sequence="M1+Y">
</key>
</extension>
<!--extension
point="org.eclipse.ui.bindings">
<scheme
id="com.raytheon.uf.viz.drawing.scheme"
name="Drawing Scheme">
</scheme>
<key
commandId="com.raytheon.uf.viz.drawing.undoadd"
contextId="com.raytheon.viz.ui.mapContext"
schemeId="com.raytheon.uf.viz.drawing.scheme"
sequence="M1+Z">
</key>
<key
commandId="com.raytheon.uf.viz.drawing.redoadd"
contextId="com.raytheon.viz.ui.mapContext"
schemeId="com.raytheon.uf.viz.drawing.scheme"
sequence="M1+Y">
</key>
</extension-->
</plugin>

View file

@ -1,121 +0,0 @@
/**
* 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.drawing;
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.core.drawables.IDescriptor;
import com.raytheon.uf.viz.core.drawables.ResourcePair;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.rsc.AbstractResourceData;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.IInputHandler;
import com.raytheon.uf.viz.core.rsc.IInputHandler.InputPriority;
import com.raytheon.uf.viz.core.rsc.LoadProperties;
import com.raytheon.uf.viz.core.rsc.ResourceList;
import com.raytheon.viz.ui.tools.AbstractModalTool;
/**
* Describes a basic drawing tool.
*
* All subclasses implement abstract method getMouseHandler() which returns how
* the drawing is handled
*
*
* @author chammack
*
*/
public abstract class AbstractDrawingTool extends AbstractModalTool {
protected static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(AbstractDrawingTool.class);
/** The drawing layer */
protected DrawingLayer theDrawingLayer;
/** The handler (if any) that has been registered */
protected IInputHandler handlerRegistered;
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.ui.tools.AbstractModalTool#deactivateTool()
*/
@Override
protected void deactivateTool() {
editor.unregisterMouseHandler(this.handlerRegistered);
}
@Override
protected void activateTool() {
theDrawingLayer = null;
IDescriptor desc = getActiveDescriptor();
ResourceList rscList = desc.getResourceList();
for (ResourcePair rp : rscList) {
AbstractVizResource<?, ?> rsc = rp.getResource();
// find a drawable layer
if (rsc instanceof DrawingLayer) {
theDrawingLayer = (DrawingLayer) rsc;
break;
}
}
if (theDrawingLayer == null) {
try {
theDrawingLayer = (DrawingLayer) constructData().construct(
new LoadProperties(), desc);
} catch (VizException e1) {
statusHandler.handle(Priority.ERROR,
"Unable to construct the drawing layer", e1);
}
try {
desc.getResourceList().add(theDrawingLayer);
theDrawingLayer.initInternal(editor.getActiveDisplayPane()
.getTarget());
} catch (Exception e) {
// ignore
}
}
if (this.handlerRegistered != null) {
editor.unregisterMouseHandler(this.handlerRegistered);
}
this.handlerRegistered = getMouseHandler();
editor.registerMouseHandler(this.handlerRegistered,
InputPriority.SYSTEM_RESOURCE);
}
/**
* This method returns a mousehandler that will be registered/unregistered
* on the editor when appropriate.
*
* The handler should interact with the drawing layer to implement drawing
* functions.
*
* @return the handler
*/
public abstract IInputHandler getMouseHandler();
protected abstract AbstractResourceData constructData();
}

View file

@ -1,447 +0,0 @@
/**
* 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.drawing;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.swt.graphics.RGB;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.google.common.eventbus.EventBus;
import com.raytheon.uf.viz.core.IGraphicsTarget;
import com.raytheon.uf.viz.core.drawables.IWireframeShape;
import com.raytheon.uf.viz.core.drawables.PaintProperties;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.map.MapDescriptor;
import com.raytheon.uf.viz.core.rsc.AbstractResourceData;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.LoadProperties;
import com.raytheon.uf.viz.core.rsc.capabilities.ColorableCapability;
import com.raytheon.uf.viz.core.rsc.capabilities.OutlineCapability;
import com.raytheon.uf.viz.drawing.events.DrawingEvent;
import com.raytheon.uf.viz.drawing.events.DrawingEventBus;
import com.raytheon.uf.viz.drawing.events.DrawingListener;
import com.raytheon.viz.ui.input.EditableManager;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.TopologyException;
/**
* Implements a basic drawing layer
*
* @author chammack
*
*/
/**
* A basic drawing layer
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* ?? chammack Initial creation
* March 30, 2012 mnash Updated to match current conventions
*
* </pre>
*
* @author mnash
* @version 1.0
*/
public class DrawingLayer extends
AbstractVizResource<AbstractResourceData, MapDescriptor> {
public static enum LayerState {
DRAWING, ERASING, NONE;
}
protected List<Geometry> tempGeometries;
protected Map<Geometry, IWireframeShape> wireframeShapes;
protected Map<Geometry, IWireframeShape> deletedShapes;
protected IWireframeShape tempWireframeShape;
protected IWireframeShape eraseWireframeShape;
protected IGraphicsTarget target;
protected LayerState state;
protected PaintProperties paintProps = null;
private boolean needsRefresh = false;
protected RGB color;
protected OutlineCapability outline;
// allowing for others to get events from the drawing tool, just having to
// subscribe
private EventBus eventBus;
private DrawingListener eventListener = null;
public DrawingLayer(PathDrawingResourceData data, LoadProperties props) {
super(data, props);
eventBus = DrawingEventBus.getEventBus();
eventListener = DrawingEventBus.getDrawingListener();
eventBus.register(eventListener);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.core.rsc.IVizResource#getName()
*/
public String getName() {
return "Telestrator Drawing Tool";
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.rsc.AbstractVizResource#init(com.raytheon.uf
* .viz.core.IGraphicsTarget)
*/
@Override
protected void initInternal(IGraphicsTarget target) throws VizException {
EditableManager.makeEditable(this, true);
this.tempGeometries = new ArrayList<Geometry>();
this.wireframeShapes = new LinkedHashMap<Geometry, IWireframeShape>();
this.deletedShapes = new LinkedHashMap<Geometry, IWireframeShape>();
this.target = target;
outline = getCapability(OutlineCapability.class);
color = getCapability(ColorableCapability.class).getColor();
}
/*
* (non-Javadoc)
*
* @seecom.raytheon.viz.core.rsc.IVizResource#paint(com.raytheon.viz.core.
* IGraphicsTarget, com.raytheon.viz.core.PixelExtent, double, float)
*/
protected void paintInternal(IGraphicsTarget target,
PaintProperties paintProps) throws VizException {
this.paintProps = paintProps;
this.color = getCapability(ColorableCapability.class).getColor();
if (tempWireframeShape == null || needsRefresh) {
tempWireframeShape = target.createWireframeShape(true,
getDescriptor());
needsRefresh = false;
}
if (eraseWireframeShape == null) {
eraseWireframeShape = target.createWireframeShape(true,
getDescriptor());
}
outline = getCapability(OutlineCapability.class);
for (IWireframeShape sh : wireframeShapes.values()) {
target.drawWireframeShape(sh, color,
(float) outline.getOutlineWidth(), outline.getLineStyle());
}
if (state == LayerState.DRAWING) {
for (Geometry g : this.tempGeometries) {
drawTempLinePrimitive(g, tempWireframeShape);
}
target.drawWireframeShape(tempWireframeShape, color,
outline.getOutlineWidth(), outline.getLineStyle());
}
}
/**
* Add the geometry to the wireframe shape that is passed in
*
* @param shape
* @param wShape
*/
protected void drawTempLinePrimitive(Geometry shape, IWireframeShape wShape) {
LineString line = (LineString) shape;
int pts = line.getNumPoints();
for (int i = 1; i < pts; i++) {
double[] p1 = new double[] { line.getPointN(i - 1).getX(),
line.getPointN(i - 1).getY() };
double[] p2 = new double[] { line.getPointN(i).getX(),
line.getPointN(i).getY() };
double[][] coords = new double[2][2];
coords[0][0] = p1[0];
coords[0][1] = p1[1];
coords[1][0] = p2[0];
coords[1][1] = p2[1];
wShape.addLineSegment(coords);
}
}
/**
* Convert from world to gl pixels
*
* @param line
* @param i
* @return
*/
public LineString convertPixels(LineString line, boolean pixelToWorld) {
int pts = line.getNumPoints();
GeometryFactory factory = new GeometryFactory();
List<Coordinate> coords = new ArrayList<Coordinate>();
for (int i = 0; i < pts; i++) {
double[] point = null;
if (pixelToWorld) {
point = this.descriptor.pixelToWorld(new double[] {
line.getPointN(i).getX(), line.getPointN(i).getY() });
} else {
point = this.descriptor.worldToPixel(new double[] {
line.getPointN(i).getX(), line.getPointN(i).getY() });
}
coords.add(new Coordinate(point[0], point[1]));
}
return factory.createLineString(coords.toArray(new Coordinate[0]));
}
/**
* Finalize a temporary line by putting it in the map of all the drawn
* shapes
*
* UUID is optional, an generally should be null
*
* @param line
* @param isFinal
* @param uuid
*/
public void finalizeLine(LineString line, String uuid) {
if (state == LayerState.DRAWING) {
tempWireframeShape.compile();
wireframeShapes.put(line, tempWireframeShape);
}
// this will update the toolbar if necessary
DrawingEvent event = new DrawingEvent();
eventBus.post(event);
}
public void addTempDrawLine(LineString line) {
this.tempGeometries.add(line);
}
public void addTempEraseLine(LineString line) {
// this.tempGeometries.add(line);
Map<Geometry, IWireframeShape> shapes = new HashMap<Geometry, IWireframeShape>();
shapes.putAll(wireframeShapes);
for (Geometry geom : shapes.keySet()) {
double extentPercentageX = paintProps.getView().getExtent()
.getWidth()
/ (double) paintProps.getCanvasBounds().width;
double cursorSize = 16;
double size = extentPercentageX * cursorSize;
if (line.buffer(size / 2).intersects(geom)) {
Geometry intersection = line.buffer(size / 2)
.intersection(geom);
Geometry finalGeom = null;
try {
finalGeom = geom.difference(intersection);
} catch (TopologyException e) {
continue;
}
deletedShapes.put(geom, wireframeShapes.remove(geom));
Geometry lString = null;
// should be split into multiple pieces (half or more)
if (finalGeom instanceof MultiLineString) {
lString = (MultiLineString) finalGeom;
for (int j = 0; j < lString.getNumGeometries(); j++) {
LineString lineString = (LineString) lString
.getGeometryN(j);
eraseWireframeShape = target.createWireframeShape(true,
descriptor);
drawTempLinePrimitive(lineString, eraseWireframeShape);
this.wireframeShapes.put(lineString,
eraseWireframeShape);
}
}
if (finalGeom instanceof LineString) {
GeometryFactory factory = new GeometryFactory();
lString = (LineString) finalGeom;
Point point = factory
.createPoint(lString.getCoordinates()[0]);
intersection = point.buffer(size / 2).intersection(geom);
finalGeom = geom.difference(intersection);
eraseWireframeShape = target.createWireframeShape(true,
descriptor);
drawTempLinePrimitive(lString, eraseWireframeShape);
this.wireframeShapes.put(lString, eraseWireframeShape);
}
}
tempGeometries.clear();
}
}
public void reset() {
resetTemp();
disposeShapes();
issueRefresh();
}
/**
* reset the temporary geometries so that we can start a new line
*/
public void resetTemp() {
this.tempGeometries.clear();
needsRefresh = true;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.core.rsc.IVizResource#dispose()
*/
@Override
protected void disposeInternal() {
disposeShapes();
}
private void disposeShapes() {
for (IWireframeShape shape : this.wireframeShapes.values()) {
shape.dispose();
}
for (IWireframeShape shape : this.deletedShapes.values()) {
shape.dispose();
}
if (this.tempWireframeShape != null) {
this.tempWireframeShape.dispose();
}
if (this.eraseWireframeShape != null) {
this.eraseWireframeShape.dispose();
}
this.wireframeShapes.clear();
this.deletedShapes.clear();
}
/**
* Remove the last drawn shape
*/
public void undoAdd() {
if (!this.wireframeShapes.isEmpty()) {
Geometry geom = this.wireframeShapes.keySet().toArray(
new Geometry[0])[this.wireframeShapes.size() - 1];
deletedShapes.put(geom, this.wireframeShapes.remove(geom));
issueRefresh();
}
}
/**
* Redraw the last deleted shape
*/
public void redoAdd() {
if (!deletedShapes.isEmpty()) {
Geometry geom = this.deletedShapes.keySet()
.toArray(new Geometry[0])[this.deletedShapes.size() - 1];
this.wireframeShapes.put(geom, this.deletedShapes.remove(geom));
issueRefresh();
}
}
/**
* @return the deletedShapes, these shapes will get disposed when the clear
* button is selected
*/
public Map<Geometry, IWireframeShape> getDeletedShapes() {
return deletedShapes;
}
/**
* @return the wireframeShapes, these shapes will get disposed when the
* clear button is selected
*/
public Map<Geometry, IWireframeShape> getWireframeShapes() {
return wireframeShapes;
}
/**
* @return the eventBus
*/
public EventBus getEventBus() {
return eventBus;
}
/**
* @return the eventListener
*/
public DrawingListener getEventListener() {
return eventListener;
}
/**
* @return the state
*/
public LayerState getState() {
return state;
}
/**
* @param state
* the state to set
*/
public void setState(LayerState state) {
this.state = state;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.rsc.AbstractVizResource#project(org.opengis.
* referencing.crs.CoordinateReferenceSystem)
*/
@Override
public void project(CoordinateReferenceSystem crs) throws VizException {
GeometryFactory factory = new GeometryFactory();
Map<Geometry, IWireframeShape> shapes = new HashMap<Geometry, IWireframeShape>();
shapes.putAll(wireframeShapes);
for (Geometry geom : shapes.keySet()) {
IWireframeShape shape = target.createWireframeShape(true,
getDescriptor());
Coordinate[] newCoords = new Coordinate[geom.getCoordinates().length];
for (int i = 0; i < geom.getNumGeometries(); i++) {
Geometry ls = convertPixels((LineString) geom.getGeometryN(i),
true);
drawTempLinePrimitive((LineString) ls, shape);
}
// wireframeShapes.remove(geom);
// wireframeShapes.put(line, shape);
}
}
}

View file

@ -0,0 +1,692 @@
/**
* 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.drawing;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.geotools.coverage.grid.GeneralGridGeometry;
import org.geotools.geometry.jts.JTS;
import org.geotools.referencing.operation.DefaultMathTransformFactory;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.datum.PixelInCell;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import com.raytheon.uf.common.geospatial.TransformFactory;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.core.IExtent;
import com.raytheon.uf.viz.core.IGraphicsTarget;
import com.raytheon.uf.viz.core.IGraphicsTarget.LineStyle;
import com.raytheon.uf.viz.core.drawables.IRenderable;
import com.raytheon.uf.viz.core.drawables.IWireframeShape;
import com.raytheon.uf.viz.core.drawables.PaintProperties;
import com.raytheon.uf.viz.core.exception.VizException;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryCollection;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.TopologyException;
/**
* Drawing layer that can draw lines and handle undo/redo/clear/erase
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* May 23, 2012 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class DrawingToolLayer implements IRenderable {
public static enum DrawMode {
NONE, DRAW, ERASE;
}
private static class StackFrame {
/** The collection of geometries displayed at a given frame */
private Collection<Geometry> geometries;
public StackFrame(Collection<Geometry> geometries) {
this.geometries = geometries;
}
}
/** The factory used for geometry construction */
private static final GeometryFactory factory = new GeometryFactory();
/**
* Stack for undo operations. Currently size is unlimited, may want to limit
* to specific size at some point
*/
private Stack<StackFrame> undoStack;
/** Stack for redo operations */
private Stack<StackFrame> redoStack;
/** Wireframe shape for display of currentData frame */
private IWireframeShape wireframeShape;
/** Currently displayed frame */
private StackFrame currentData;
/** Color of the data */
private RGB color = new RGB(155, 155, 155);
/** Line width of the data */
private int lineWidth = 2;
/** Eraser width to use when erasing */
private int eraserWidth = 4;
/** Line style of the data drawn */
private LineStyle lineStyle = LineStyle.DEFAULT;
/**
* Draw mode of the data (NONE,DRAW,ERASE). Used when
* {@link #addCoordinate(Coordinate)} is called
*/
private DrawMode drawMode = DrawMode.NONE;
/**
* The line currently being drawn through {@link #addCoordinate(Coordinate)}
* calls before {@link #doneDrawing()} is called
*/
private Geometry currentDrawingLine;
/**
* The line currently being drawn through {@link #addCoordinate(Coordinate)}
* calls before {@link #doneErasing()} is called
*/
private Geometry currentErasingLine;
/**
* Flag that erasing is finished and a new stack frame should be created
* next time {@link #processErase(IExtent, Rectangle)} is called
*/
private boolean addErasingEventToStack = false;
/** The {@link GeneralGridGeometry} we are drawing to */
private GeneralGridGeometry targetGeometry;
/**
* Cached "world" to grid {@link MathTransform} ({@link StackFrame}
* geometries are stored in grid space)
*/
private MathTransform worldToGrid;
/**
* Construct a DrawingToolLayer that will draw to the
* {@link GeneralGridGeometry} passed in
*
* @param targetGeometry
*/
public DrawingToolLayer(GeneralGridGeometry targetGeometry) {
setTargetGeometry(targetGeometry);
undoStack = new Stack<StackFrame>();
redoStack = new Stack<StackFrame>();
currentData = new StackFrame(new ArrayList<Geometry>(0));
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.drawables.IRenderable#paint(com.raytheon.uf.
* viz.core.IGraphicsTarget,
* com.raytheon.uf.viz.core.drawables.PaintProperties)
*/
@Override
public void paint(IGraphicsTarget target, PaintProperties paintProps)
throws VizException {
synchronized (currentData) {
// Process erase coordinates before drawing data for current frame
processErase(paintProps.getView().getExtent(),
paintProps.getCanvasBounds());
if (wireframeShape == null && currentData.geometries.size() > 0) {
// No wireframe shape and we have data, create for drawing
wireframeShape = target.createWireframeShape(false,
targetGeometry);
int totalPoints = 0;
for (Geometry geom : currentData.geometries) {
totalPoints += geom.getNumPoints();
}
wireframeShape.allocate(totalPoints * 3 * 8);
for (Geometry geom : currentData.geometries) {
handle(wireframeShape, geom);
}
wireframeShape.compile();
}
if (wireframeShape != null) {
// We have data to draw, draw it
target.drawWireframeShape(wireframeShape, color, lineWidth,
lineStyle);
}
// Render any line currently being drawn through addCoordinate(...)
if (currentDrawingLine != null
&& currentDrawingLine.getNumPoints() > 1) {
IWireframeShape tmpShape = target.createWireframeShape(true,
targetGeometry);
tmpShape.allocate(currentDrawingLine.getNumPoints() * 3 * 8);
handle(tmpShape, currentDrawingLine);
target.drawWireframeShape(tmpShape, color, lineWidth, lineStyle);
tmpShape.dispose();
}
}
}
/**
* Processes the erase line currently constructed from
* {@link #addCoordinate(Coordinate)} while in "ERASE" {@link DrawMode}
*
* @param extent
* @param canvasSize
*/
public void processErase(IExtent extent, Rectangle canvasSize) {
synchronized (currentData) {
if (currentErasingLine != null
&& currentErasingLine.getNumPoints() > 0) {
// Calculate world grid to canvas grid ratio
double ratio = extent.getWidth() / canvasSize.width;
// Get the size to buffer the eraser line for differencing
double bufferSize = (ratio * eraserWidth) / 2;
// Flatten all eraser line geometries into a single list
List<Geometry> eraserLines = new ArrayList<Geometry>(
currentErasingLine.getNumGeometries());
flattenGeometry(currentErasingLine, eraserLines);
boolean change = false;
List<Geometry> currentGeoms = new ArrayList<Geometry>(
currentData.geometries);
List<Geometry> newGeoms = new ArrayList<Geometry>(
currentGeoms.size());
// For each eraser line, run against currentData
for (Geometry eraserLine : eraserLines) {
eraserLine = eraserLine.buffer(bufferSize);
newGeoms = new ArrayList<Geometry>(currentGeoms.size());
for (Geometry geom : currentGeoms) {
if (geom.intersects(eraserLine)) {
// Eraser line intersects, create difference
Geometry diff = geom.difference(eraserLine);
// Mark change flag
change = true;
if (diff instanceof GeometryCollection == false) {
// To avoid self intersecting lines, this
// will split the difference geometry
Coordinate[] coords = diff.getCoordinates();
diff = diff.union(factory
.createPoint(coords[0]));
}
// Add diff to newGeoms
flattenGeometry(diff, newGeoms);
} else {
// Add old geometry, no changes
newGeoms.add(geom);
}
}
// These are the new "currentGeoms" for the next eraser line
currentGeoms = newGeoms;
}
if (change) {
if (addErasingEventToStack) {
// If data changed and we should add a new frame, do it
addErasingEventToStack = false;
addCurrentDataToStack(undoStack);
redoStack.clear();
} else if (wireframeShape != null) {
// In else if since addCurrentDataToStack will destroy
// wireframeShape for us
wireframeShape.dispose();
wireframeShape = null;
}
}
// Current data is now what is in newGeoms
currentData.geometries = newGeoms;
currentErasingLine = null;
}
}
}
/**
* Recursively adds LineString objects in the geom to wireframeShape
*
* @param wireframeShape
* @param geom
*/
private void handle(IWireframeShape wireframeShape, Geometry geom) {
if (geom instanceof GeometryCollection) {
for (int n = 0; n < geom.getNumGeometries(); ++n) {
handle(wireframeShape, geom.getGeometryN(n));
}
} else if (geom instanceof LineString) {
Coordinate[] coords = geom.getCoordinates();
double[][] points = new double[coords.length][];
for (int i = 0; i < coords.length; ++i) {
points[i] = new double[] { coords[i].x, coords[i].y,
coords[i].z };
}
wireframeShape.addLineSegment(points);
}
}
/**
* Disposes the data in the layer
*/
public void dispose() {
synchronized (currentData) {
if (wireframeShape != null) {
wireframeShape.dispose();
}
currentData.geometries.clear();
currentDrawingLine = null;
undoStack.clear();
redoStack.clear();
}
}
/**
* Adds a coordinate to the layer, coordinate is processed based on
* {@link #drawMode}. Coordinate should be in {@link #targetGeometry}
* "world" spacing
*
* @param coord
*/
public void addCoordinate(Coordinate coord) {
synchronized (currentData) {
// Convert coord to targetGeometry grid space
double[] point = new double[] { coord.x, coord.y, coord.z };
if (worldToGrid != null) {
double[] out = new double[point.length];
try {
worldToGrid.transform(point, 0, out, 0, 1);
point = out;
} catch (TransformException e) {
UFStatus.getHandler().handle(Priority.PROBLEM,
e.getLocalizedMessage(), e);
}
}
Coordinate newCoord = new Coordinate(point[0], point[1], point[2]);
Geometry toAddto = null;
if (drawMode == DrawMode.DRAW) {
if (currentDrawingLine == null) {
currentDrawingLine = factory.createPoint(newCoord);
} else {
toAddto = currentDrawingLine;
}
} else if (drawMode == DrawMode.ERASE) {
if (currentErasingLine == null) {
currentErasingLine = factory.createPoint(newCoord);
} else {
toAddto = currentErasingLine;
}
}
if (toAddto != null) {
// This will flatten the new line into a geometry collection so
// it is not self intersecting and errors will not occur
int numGeoms = toAddto.getNumGeometries();
// The last geometry in the collection is the one to append the
// coordinate to
Geometry last = toAddto.getGeometryN(numGeoms - 1);
Coordinate[] coords = last.getCoordinates();
Coordinate[] newCoords = Arrays.copyOf(coords,
coords.length + 1);
newCoords[newCoords.length - 1] = newCoord;
Geometry newGeom = null;
try {
// Create new LineString with newCoords
newGeom = factory.createLineString(newCoords).union(
factory.createPoint(coords[0]));
} catch (TopologyException e) {
// Can't keep adding to this line, create new one from last
// coordinate and newGeom will be collection with both
newGeom = factory.createGeometryCollection(new Geometry[] {
last,
factory.createLineString(new Coordinate[] {
coords[coords.length - 1], newCoord }) });
}
List<Geometry> newGeoms = new ArrayList<Geometry>(numGeoms);
for (int n = 0; n < numGeoms - 1; ++n) {
// Don't grab the last one (newGeoms - 1) since it will be
// included in newGeom
newGeoms.add(toAddto.getGeometryN(n));
}
if (newGeoms.size() > 0) {
// geoms still in toAddto, flatten our newGeom object into
// newGeoms list and create collection
flattenGeometry(newGeom, newGeoms);
newGeom = factory.createGeometryCollection(newGeoms
.toArray(new Geometry[newGeoms.size()]));
}
// Set newGeom to proper line
if (toAddto == currentDrawingLine) {
currentDrawingLine = newGeom;
} else {
currentErasingLine = newGeom;
}
}
}
}
/**
* Should be called when no more coordinates will be added to
* {@link #addCoordinate(Coordinate)} and the line should be processed as
* is. A new stack frame will be created with the new line in it
*/
public void doneDrawing() {
synchronized (currentData) {
if (currentDrawingLine != null
&& currentDrawingLine.getNumPoints() > 1) {
// Have data to process
try {
addCurrentDataToStack(undoStack);
List<Geometry> newGeometries = new ArrayList<Geometry>(
currentData.geometries);
flattenGeometry(currentDrawingLine, newGeometries);
currentData.geometries = newGeometries;
redoStack.clear();
} catch (Exception e) {
UFStatus.getHandler().handle(Priority.PROBLEM,
"Could not add line, bad geometry", e);
}
currentDrawingLine = null;
}
}
}
/**
* Recursively adds all non GeometryCollection geometries to geoms
*
* @param geom
* @param geoms
*/
public void flattenGeometry(Geometry geom, List<Geometry> geoms) {
if (geom instanceof GeometryCollection) {
for (int n = 0; n < geom.getNumGeometries(); ++n) {
flattenGeometry(geom.getGeometryN(n), geoms);
}
} else {
geoms.add(geom);
}
}
/**
* Should be called when no more coordinates will be added to
* {@link #addCoordinate(Coordinate)} and the line should be processed as
* is. A new stack frame will be created with the new line in it
*/
public void doneErasing() {
synchronized (currentData) {
addErasingEventToStack = true;
}
}
/**
* Returns true if an undo operation is capable of being processed
*
* @return
*/
public boolean canUndo() {
return undoStack.size() > 0;
}
/**
* Returns true if a redo operation is capable of being processed
*
* @return
*/
public boolean canRedo() {
return redoStack.size() > 0;
}
/**
* Returns true if a clear operation is capable of being processed
*
* @return
*/
public boolean canClear() {
return currentData.geometries.size() > 0 || redoStack.size() > 0;
}
/**
* Undo the last drawing action
*/
public void undo() {
pushPop(undoStack, redoStack);
}
/**
* Redo the last undone drawing action
*/
public void redo() {
pushPop(redoStack, undoStack);
}
/**
* Clears the current display, a new stack frame is created. This operation
* is "undoable" by calling {@link #undo()}
*/
public void clear() {
synchronized (currentData) {
if (currentData.geometries.size() > 0) {
addCurrentDataToStack(undoStack);
currentData.geometries.clear();
}
redoStack.clear();
}
}
/**
* Pushes currentData on pushStack and pops next frame from popStack and
* puts in currentData
*
* @param user
* @param popFrom
* @param pushTo
*/
private void pushPop(Stack<StackFrame> popFrom, Stack<StackFrame> pushTo) {
synchronized (currentData) {
if (popFrom.size() > 0) {
// There is something to undo, add current data to redoStack
addCurrentDataToStack(pushTo);
StackFrame prevFrame = popFrom.pop();
currentData.geometries = new ArrayList<Geometry>(
prevFrame.geometries);
}
}
}
/**
* Method to add the current data for the user to the user's stack. This
* method is not thread safe and needs to be wrapped in a synchronize block
* on currentData. Returns the current data for the user which will no
* longer be in currentData
*
* @param user
* @return
*/
private void addCurrentDataToStack(Stack<StackFrame> stack) {
StackFrame oldData = new StackFrame(new ArrayList<Geometry>(
currentData.geometries));
stack.push(oldData);
if (wireframeShape != null) {
wireframeShape.dispose();
wireframeShape = null;
}
}
/**
* @param color
* the color to set
*/
public void setColor(RGB color) {
this.color = color;
}
/**
* @param lineWidth
* the lineWidth to set
*/
public void setLineWidth(int lineWidth) {
this.lineWidth = lineWidth;
}
/**
* @param lineStyle
* the lineStyle to set
*/
public void setLineStyle(LineStyle lineStyle) {
this.lineStyle = lineStyle;
}
/**
* @param eraserWidth
* the eraserWidth to set
*/
public void setEraserWidth(int eraserWidth) {
this.eraserWidth = eraserWidth;
}
/**
* @return the drawMode
*/
public DrawMode getDrawMode() {
return drawMode;
}
/**
* @param drawMode
* the drawMode to set
*/
public void setDrawMode(DrawMode drawMode) {
if (this.drawMode != drawMode) {
this.drawMode = drawMode;
currentDrawingLine = null;
}
}
private void setTargetGeometry(GeneralGridGeometry targetGeometry) {
try {
this.targetGeometry = targetGeometry;
this.worldToGrid = TransformFactory.worldToGrid(targetGeometry,
PixelInCell.CELL_CENTER);
} catch (FactoryException e) {
UFStatus.getHandler().handle(Priority.PROBLEM,
e.getLocalizedMessage(), e);
}
}
/**
* Reprojects the layer data for the new targetGeometry
*
* @param targetGeometry
*/
public void reproject(GeneralGridGeometry targetGeometry) {
synchronized (currentData) {
MathTransform concatenatedTransform = null;
try {
MathTransform worldToOldGrid = worldToGrid;
if (worldToOldGrid != null) {
concatenatedTransform = worldToOldGrid.inverse();
}
setTargetGeometry(targetGeometry);
if (worldToGrid != null) {
if (concatenatedTransform != null) {
concatenatedTransform = new DefaultMathTransformFactory()
.createConcatenatedTransform(
concatenatedTransform, worldToGrid);
} else {
concatenatedTransform = worldToGrid;
}
}
} catch (Exception e) {
UFStatus.getHandler().handle(Priority.PROBLEM,
e.getLocalizedMessage(), e);
}
if (concatenatedTransform != null) {
Map<Geometry, Geometry> projectionMap = new HashMap<Geometry, Geometry>();
for (StackFrame sf : undoStack) {
sf.geometries = reprojectCollection(sf.geometries,
projectionMap, concatenatedTransform);
}
for (StackFrame sf : redoStack) {
sf.geometries = reprojectCollection(sf.geometries,
projectionMap, concatenatedTransform);
}
currentData.geometries = reprojectCollection(
currentData.geometries, projectionMap,
concatenatedTransform);
}
if (wireframeShape != null) {
wireframeShape.dispose();
wireframeShape = null;
}
}
}
private Collection<Geometry> reprojectCollection(
Collection<Geometry> geometries, Map<Geometry, Geometry> cache,
MathTransform transform) {
List<Geometry> newGeoms = new ArrayList<Geometry>(geometries.size());
for (Geometry geom : geometries) {
Geometry projected = cache.get(geom);
if (projected == null) {
try {
projected = JTS.transform(geom, transform);
} catch (Exception e) {
UFStatus.getHandler().handle(Priority.PROBLEM,
e.getLocalizedMessage(), e);
}
cache.put(geom, projected);
}
if (projected != null) {
newGeoms.add(projected);
}
}
return newGeoms;
}
}

View file

@ -0,0 +1,153 @@
/**
* 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.drawing;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import com.raytheon.uf.viz.core.IDisplayPaneContainer;
import com.raytheon.uf.viz.core.icon.IconUtil;
import com.raytheon.uf.viz.drawing.DrawingToolLayer.DrawMode;
import com.raytheon.viz.ui.input.InputAdapter;
import com.vividsolutions.jts.geom.Coordinate;
/**
* UI manager for a DrawingToolLayer, handles mouse actions for drawing
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* May 23, 2012 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class DrawingToolUIManager extends InputAdapter {
private DrawingToolLayer drawingLayer;
private Cursor erasor;
private Cursor pencil;
private Cursor normal;
protected IDisplayPaneContainer container;
private Shell currentShell = null;
public DrawingToolUIManager(DrawingToolLayer drawingLayer,
IDisplayPaneContainer container) {
this.drawingLayer = drawingLayer;
// Create erasor cursor
ImageData data = IconUtil.getImageDescriptor(
Activator.getDefault().getBundle(), "eraser_box.gif")
.getImageData();
data.alpha = 255;
erasor = new Cursor(Display.getCurrent(), data, 8, 8);
// Create pencil cursor
pencil = new Cursor(Display.getCurrent(), SWT.CURSOR_HAND);
this.container = container;
container.registerMouseHandler(this);
}
public void dispose() {
erasor.dispose();
pencil.dispose();
container.unregisterMouseHandler(this);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.ui.input.InputAdapter#handleMouseDown(int, int,
* int)
*/
@Override
public boolean handleMouseDown(int x, int y, int mouseButton) {
if (mouseButton != 1 || drawingLayer.getDrawMode() == DrawMode.NONE
|| currentShell != null) {
return false;
}
currentShell = Display.getCurrent().getActiveShell();
if (drawingLayer.getDrawMode() == DrawMode.DRAW) {
currentShell.setCursor(pencil);
} else {
currentShell.setCursor(erasor);
}
return handleMouseDownMove(x, y, mouseButton);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.ui.input.InputAdapter#handleMouseDownMove(int, int,
* int)
*/
@Override
public boolean handleMouseDownMove(int x, int y, int mouseButton) {
if (currentShell == null) {
return false;
}
Coordinate c = container.translateClick(x, y);
if (c != null) {
drawingLayer.addCoordinate(c);
}
container.refresh();
return true;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.ui.input.InputAdapter#handleMouseUp(int, int, int)
*/
@Override
public boolean handleMouseUp(int x, int y, int mouseButton) {
if (currentShell == null) {
return false;
}
currentShell.setCursor(normal);
if (drawingLayer.getDrawMode() == DrawMode.DRAW) {
drawingLayer.doneDrawing();
} else {
drawingLayer.doneErasing();
}
container.refresh();
currentShell = null;
return true;
}
}

View file

@ -0,0 +1,259 @@
/**
* 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.drawing;
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.Composite;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import com.raytheon.uf.viz.core.icon.IconUtil;
import com.raytheon.uf.viz.drawing.DrawingToolLayer.DrawMode;
import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
/**
* Toolbar dialog for DrawingToolLayer
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* May 23, 2012 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class DrawingToolbar extends CaveSWTDialog {
private DrawingToolLayer layer;
protected ToolItem drawItem;
protected ToolItem eraserItem;
protected ToolItem undoItem;
protected ToolItem redoItem;
protected ToolItem clearItem;
/**
* @param parentShell
*/
public DrawingToolbar(Shell parent) {
super(parent, SWT.DIALOG_TRIM, CAVE.PERSPECTIVE_INDEPENDENT
| CAVE.DO_NOT_BLOCK);
setText("Drawing Tool");
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.viz.ui.dialogs.CaveSWTDialogBase#initializeComponents(org
* .eclipse.swt.widgets.Shell)
*/
@Override
protected void initializeComponents(Shell shell) {
Composite comp = new Composite(shell, SWT.NONE);
GridLayout layout = new GridLayout();
comp.setLayout(layout);
GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
comp.setLayoutData(data);
layout.marginHeight = 0;
layout.marginWidth = 0;
ToolBar toolbar = new ToolBar(comp, SWT.FLAT);
layout = new GridLayout();
layout.marginHeight = 0;
layout.marginWidth = 0;
data = new GridData(SWT.FILL, SWT.FILL, true, true);
toolbar.setLayout(layout);
toolbar.setLayoutData(data);
addToolsToToolBar(toolbar);
nullLayer();
}
/**
* @param toolbar
*/
protected void addToolsToToolBar(ToolBar toolbar) {
// Draw button
drawItem = new ToolItem(toolbar, SWT.CHECK);
drawItem.setText("Draw");
drawItem.setImage(IconUtil.getImageDescriptor(
Activator.getDefault().getBundle(), "draw.gif").createImage());
drawItem.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (drawItem.getSelection()) {
layer.setDrawMode(DrawMode.DRAW);
} else if (eraserItem.getSelection() == false) {
layer.setDrawMode(DrawMode.NONE);
}
updateItemState();
}
});
// Undo button
undoItem = new ToolItem(toolbar, SWT.FLAT);
undoItem.setText("Undo");
undoItem.setImage(IconUtil.getImageDescriptor(
Activator.getDefault().getBundle(), "undo.gif").createImage());
undoItem.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
undo();
}
});
// Redo button
redoItem = new ToolItem(toolbar, SWT.FLAT);
redoItem.setText("Redo");
redoItem.setImage(IconUtil.getImageDescriptor(
Activator.getDefault().getBundle(), "redo.gif").createImage());
redoItem.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
redo();
}
});
// Clear button
clearItem = new ToolItem(toolbar, SWT.FLAT);
clearItem.setText("Clear");
clearItem
.setImage(IconUtil.getImageDescriptor(
Activator.getDefault().getBundle(), "remove.gif")
.createImage());
clearItem.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
clear();
}
});
// Erase button
eraserItem = new ToolItem(toolbar, SWT.CHECK);
eraserItem.setText("Eraser");
eraserItem
.setImage(IconUtil.getImageDescriptor(
Activator.getDefault().getBundle(), "eraser.png")
.createImage());
eraserItem.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (eraserItem.getSelection()) {
layer.setDrawMode(DrawMode.ERASE);
} else if (drawItem.getSelection() == false) {
layer.setDrawMode(DrawMode.NONE);
}
updateItemState();
}
});
}
/**
* Method to setup tool items when no layer is active
*/
protected void nullLayer() {
drawItem.setSelection(false);
drawItem.setEnabled(false);
undoItem.setEnabled(false);
redoItem.setEnabled(false);
clearItem.setEnabled(false);
eraserItem.setEnabled(false);
eraserItem.setSelection(false);
}
/**
* Method to setup the tool items when there is a valid layer
*/
protected void validLayer() {
drawItem.setEnabled(true);
undoItem.setEnabled(layer.canUndo());
redoItem.setEnabled(layer.canRedo());
clearItem.setEnabled(layer.canClear());
eraserItem.setEnabled(true);
switch (layer.getDrawMode()) {
case DRAW:
drawItem.setSelection(true);
eraserItem.setSelection(false);
break;
case ERASE:
drawItem.setSelection(false);
eraserItem.setSelection(true);
break;
case NONE:
drawItem.setSelection(false);
eraserItem.setSelection(false);
break;
}
}
public void setCurrentDrawingLayer(DrawingToolLayer layer) {
this.layer = layer;
updateItemState();
}
/**
* Update the tool item state based on the layer
*/
protected final void updateItemState() {
if (layer == null) {
nullLayer();
} else {
validLayer();
}
getShell().layout();
}
protected void undo() {
if (layer != null) {
layer.undo();
updateItemState();
}
}
protected void redo() {
if (layer != null) {
layer.redo();
updateItemState();
}
}
protected void clear() {
if (layer != null) {
layer.clear();
updateItemState();
}
}
}

View file

@ -1,342 +0,0 @@
/**
* 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.drawing;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.contexts.IContextActivation;
import org.eclipse.ui.contexts.IContextService;
import com.google.common.eventbus.AllowConcurrentEvents;
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.viz.core.drawables.IDescriptor;
import com.raytheon.uf.viz.core.drawables.ResourcePair;
import com.raytheon.uf.viz.core.icon.IconUtil;
import com.raytheon.uf.viz.drawing.DrawingLayer.LayerState;
import com.raytheon.uf.viz.drawing.actions.ClearDrawingAction;
import com.raytheon.uf.viz.drawing.actions.EraseObjectsAction;
import com.raytheon.uf.viz.drawing.actions.RedoAddAction;
import com.raytheon.uf.viz.drawing.actions.UndoAddAction;
import com.raytheon.uf.viz.drawing.events.DrawingEvent;
import com.raytheon.uf.viz.drawing.events.DrawingEventBus;
import com.raytheon.uf.viz.drawing.tools.PathDrawingTool;
import com.raytheon.viz.ui.EditorUtil;
import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
import com.raytheon.viz.ui.editor.AbstractEditor;
import com.raytheon.viz.ui.perspectives.VizPerspectiveListener;
import com.raytheon.viz.ui.tools.AbstractModalTool;
/**
* The dialog that holds the toolbar for the path drawing tool, interacts with
* the layer
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 28, 2012 mnash Initial creation
*
* </pre>
*
* @author mnash
* @version 1.0
*/
public class PathToolbar extends CaveSWTDialog {
protected static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(PathToolbar.class);
private static final String EDIT_TOOL_CATEGY = "com.raytheon.viz.ui.modalTool.nav";
protected static AbstractModalTool lastTool = null;
protected static PathToolbar pathToolbar;
protected ToolBar toolbar;
protected ToolItem drawItem;
protected ToolItem eraserItem;
protected ToolItem undoItem;
protected ToolItem redoItem;
protected ToolItem clearItem;
private IContextActivation drawingContext;
public static PathToolbar getToolbar() {
if (pathToolbar == null) {
pathToolbar = new PathToolbar(new Shell(Display.getCurrent()));
DrawingEventBus.register(PathToolbar.getToolbar());
}
return pathToolbar;
}
/**
* @param parentShell
* @param swtStyle
*/
protected PathToolbar(Shell parentShell) {
super(parentShell, SWT.DIALOG_TRIM | CAVE.DO_NOT_BLOCK);
setText("Drawing");
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.viz.ui.dialogs.CaveSWTDialogBase#initializeComponents(org
* .eclipse.swt.widgets.Shell)
*/
@Override
protected void initializeComponents(Shell shell) {
lastTool = VizPerspectiveListener.getCurrentPerspectiveManager()
.getToolManager().getSelectedModalTool(EDIT_TOOL_CATEGY);
shell.addShellListener(new ShellAdapter() {
@Override
public void shellClosed(ShellEvent e) {
PathToolbar.getToolbar().getShell().removeShellListener(this);
IContextService contextService = (IContextService) PlatformUI
.getWorkbench().getService(IContextService.class);
contextService.deactivateContext(drawingContext);
super.shellClosed(e);
}
});
Composite comp = new Composite(shell, SWT.NONE);
GridLayout layout = new GridLayout();
comp.setLayout(layout);
GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
comp.setLayoutData(data);
layout.marginHeight = 0;
layout.marginWidth = 0;
toolbar = new ToolBar(comp, SWT.FLAT);
layout = new GridLayout();
layout.marginHeight = 0;
layout.marginWidth = 0;
data = new GridData(SWT.FILL, SWT.FILL, true, true);
toolbar.setLayout(layout);
toolbar.setLayoutData(data);
drawItem = new ToolItem(toolbar, SWT.CHECK);
drawItem.setText("Draw");
drawItem.setImage(IconUtil.getImageDescriptor(
Activator.getDefault().getBundle(), "draw.gif").createImage());
getDrawingResource().setState(LayerState.NONE);
drawItem.setSelection(false);
drawItem.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
DrawingLayer layer = getDrawingResource();
if (layer != null) {
switch (layer.getState()) {
case DRAWING:
lastTool.activate();
layer.setState(LayerState.NONE);
break;
case ERASING:
layer.setState(LayerState.DRAWING);
eraserItem.setSelection(false);
break;
case NONE:
layer.setState(LayerState.DRAWING);
break;
}
}
updateToolbar();
}
});
undoItem = new ToolItem(toolbar, SWT.FLAT);
undoItem.setText("Undo");
undoItem.setImage(IconUtil.getImageDescriptor(
Activator.getDefault().getBundle(), "undo.gif").createImage());
undoItem.setToolTipText("Ctrl+Z to Undo");
undoItem.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
UndoAddAction action = new UndoAddAction();
executeAction(action);
updateToolbar();
}
});
redoItem = new ToolItem(toolbar, SWT.FLAT);
redoItem.setText("Redo");
redoItem.setImage(IconUtil.getImageDescriptor(
Activator.getDefault().getBundle(), "redo.gif").createImage());
redoItem.setToolTipText("Ctrl+Y to Redo");
redoItem.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
RedoAddAction action = new RedoAddAction();
executeAction(action);
updateToolbar();
}
});
clearItem = new ToolItem(toolbar, SWT.FLAT);
clearItem.setText("Clear");
clearItem
.setImage(IconUtil.getImageDescriptor(
Activator.getDefault().getBundle(), "remove.gif")
.createImage());
clearItem.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
ClearDrawingAction action = new ClearDrawingAction();
executeAction(action);
updateToolbar();
}
});
eraserItem = new ToolItem(toolbar, SWT.CHECK);
eraserItem.setText("Eraser");
eraserItem
.setImage(IconUtil.getImageDescriptor(
Activator.getDefault().getBundle(), "eraser.png")
.createImage());
eraserItem.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
DrawingLayer layer = getDrawingResource();
// reactivate the last tool
if (layer.getState() == LayerState.ERASING) {
lastTool.activate();
} else {
lastTool.deactivate();
}
// uncheck the draw item
drawItem.setSelection(false);
// execute the EraseObjectsAction
EraseObjectsAction action = new EraseObjectsAction();
executeAction(action);
}
});
}
@Override
protected void opened() {
IContextService contextService = (IContextService) PlatformUI
.getWorkbench().getService(IContextService.class);
drawingContext = contextService
.activateContext("com.raytheon.uf.viz.drawing.context");
updateToolbar();
super.opened();
}
private void executeAction(AbstractHandler action) {
try {
action.execute(null);
} catch (ExecutionException e) {
statusHandler.handle(Priority.ERROR, "Unable to execute action", e);
}
}
@AllowConcurrentEvents
@Subscribe
public void handleMessage(DrawingEvent event) {
updateToolbar();
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.ui.dialogs.CaveSWTDialogBase#disposed()
*/
@Override
protected void disposed() {
super.disposed();
pathToolbar = null;
}
public void updateToolbar() {
if (this.isDisposed()) {
return;
}
DrawingLayer layer = getDrawingResource();
if (toolbar != null && !toolbar.isDisposed()) {
if (layer.getDeletedShapes().isEmpty()
&& layer.getWireframeShapes().isEmpty()) {
undoItem.setEnabled(false);
redoItem.setEnabled(false);
clearItem.setEnabled(false);
} else {
clearItem.setEnabled(true);
if (layer.getDeletedShapes().isEmpty()) {
redoItem.setEnabled(false);
} else {
redoItem.setEnabled(true);
}
if (layer.getWireframeShapes().isEmpty()) {
undoItem.setEnabled(false);
} else {
undoItem.setEnabled(true);
}
}
}
}
protected DrawingLayer getDrawingResource() {
AbstractEditor editor = EditorUtil
.getActiveEditorAs(AbstractEditor.class);
IDescriptor desc = editor.getActiveDisplayPane().getDescriptor();
DrawingLayer layer = null;
for (ResourcePair pair : desc.getResourceList()) {
if (pair.getResource() instanceof DrawingLayer) {
layer = (DrawingLayer) pair.getResource();
break;
}
}
if (layer == null) {
PathDrawingTool tool = new PathDrawingTool();
tool.activate();
lastTool.deactivate();
layer = getDrawingResource();
}
return layer;
}
}

View file

@ -1,64 +0,0 @@
/**
* 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.drawing.actions;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import com.raytheon.uf.viz.core.drawables.ResourcePair;
import com.raytheon.uf.viz.core.rsc.ResourceList;
import com.raytheon.uf.viz.drawing.DrawingLayer;
import com.raytheon.viz.ui.EditorUtil;
import com.raytheon.viz.ui.editor.AbstractEditor;
/**
* Clears the drawing of the resource such that all user's shapes are removed
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 22, 2012 mnash Initial creation
*
* </pre>
*
* @author mnash
* @version 1.0
*/
public class ClearDrawingAction extends AbstractHandler {
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
ResourceList list = ((AbstractEditor) EditorUtil
.getActiveEditorAs(AbstractEditor.class))
.getActiveDisplayPane().getDescriptor().getResourceList();
for (ResourcePair pair : list) {
if (pair.getResource() instanceof DrawingLayer) {
((DrawingLayer) pair.getResource()).reset();
break;
}
}
return null;
}
}

View file

@ -1,70 +0,0 @@
/**
* 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.drawing.actions;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import com.raytheon.uf.viz.core.drawables.ResourcePair;
import com.raytheon.uf.viz.core.rsc.ResourceList;
import com.raytheon.uf.viz.drawing.DrawingLayer;
import com.raytheon.uf.viz.drawing.DrawingLayer.LayerState;
import com.raytheon.viz.ui.EditorUtil;
import com.raytheon.viz.ui.editor.AbstractEditor;
/**
* Using the eraser, clears part of the geometry
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 23, 2012 mnash Initial creation
*
* </pre>
*
* @author mnash
* @version 1.0
*/
public class EraseObjectsAction extends AbstractHandler {
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
ResourceList list = ((AbstractEditor) EditorUtil
.getActiveEditorAs(AbstractEditor.class))
.getActiveDisplayPane().getDescriptor().getResourceList();
for (ResourcePair pair : list) {
if (pair.getResource() instanceof DrawingLayer) {
DrawingLayer layer = (DrawingLayer) pair.getResource();
if (layer.getState() == LayerState.ERASING) {
layer.setState(LayerState.NONE);
} else {
layer.setState(LayerState.ERASING);
}
break;
}
}
return null;
}
}

View file

@ -1,67 +0,0 @@
/**
* 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.drawing.actions;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import com.raytheon.uf.viz.core.drawables.ResourcePair;
import com.raytheon.uf.viz.core.rsc.ResourceList;
import com.raytheon.uf.viz.drawing.DrawingLayer;
import com.raytheon.uf.viz.drawing.events.DrawingEvent;
import com.raytheon.viz.ui.EditorUtil;
import com.raytheon.viz.ui.editor.AbstractEditor;
/**
* Redraws the last shape that was undone
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 28, 2012 mnash Initial creation
*
* </pre>
*
* @author mnash
* @version 1.0
*/
public class RedoAddAction extends AbstractHandler {
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
ResourceList list = ((AbstractEditor) EditorUtil
.getActiveEditorAs(AbstractEditor.class))
.getActiveDisplayPane().getDescriptor().getResourceList();
for (ResourcePair pair : list) {
if (pair.getResource() instanceof DrawingLayer) {
((DrawingLayer) pair.getResource()).redoAdd();
((DrawingLayer) pair.getResource()).getEventBus().post(
new DrawingEvent());
break;
}
}
return null;
}
}

View file

@ -1,45 +0,0 @@
/**
* 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.drawing.events;
import com.raytheon.uf.common.serialization.ISerializableObject;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
/**
* A basic drawing event, just signifying that something happened
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 2, 2012 mnash Initial creation
*
* </pre>
*
* @author mnash
* @version 1.0
*/
@DynamicSerialize
public class DrawingEvent implements ISerializableObject {
}

View file

@ -1,74 +0,0 @@
/**
* 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.drawing.events;
import com.google.common.eventbus.EventBus;
/**
* Declare its own event bus so events can be sent efficiently
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 2, 2012 mnash Initial creation
*
* </pre>
*
* @author mnash
* @version 1.0
*/
public class DrawingEventBus {
private static EventBus eventBus;
private static DrawingListener drawingListener;
/**
* @return the eventBus
*/
public static EventBus getEventBus() {
if (eventBus == null) {
eventBus = new EventBus("DrawingEventBus");
}
return eventBus;
}
/**
* @return the drawingListener
*/
public static DrawingListener getDrawingListener() {
if (drawingListener == null) {
drawingListener = new DrawingListener();
}
return drawingListener;
}
/**
* Send in class to register in the event bus
*
* @param ob
*/
public static void register(Object ob) {
getEventBus().register(ob);
}
}

View file

@ -1,46 +0,0 @@
/**
* 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.drawing.events;
import com.google.common.eventbus.Subscribe;
/**
* The listener that drawing events use
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 2, 2012 mnash Initial creation
*
* </pre>
*
* @author mnash
* @version 1.0
*/
public class DrawingListener {
@Subscribe
public void handleMessage(DrawingEvent event) {
}
}

View file

@ -1,229 +0,0 @@
/**
* 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.drawing.tools;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.widgets.Display;
import com.raytheon.uf.viz.core.icon.IconUtil;
import com.raytheon.uf.viz.core.rsc.AbstractResourceData;
import com.raytheon.uf.viz.core.rsc.IInputHandler;
import com.raytheon.uf.viz.core.rsc.capabilities.EditableCapability;
import com.raytheon.uf.viz.drawing.AbstractDrawingTool;
import com.raytheon.uf.viz.drawing.Activator;
import com.raytheon.uf.viz.drawing.DrawingLayer.LayerState;
import com.raytheon.uf.viz.drawing.PathDrawingResourceData;
import com.raytheon.viz.ui.input.EditableManager;
import com.raytheon.viz.ui.input.InputAdapter;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
/**
* Draw unmodified path shapes (i.e. "pencil tool")
*
* @author chammack
*
*/
public class PathDrawingTool extends AbstractDrawingTool {
/** The mouse handler */
protected IInputHandler theHandler;
public AbstractResourceData constructData() {
PathDrawingResourceData data = new PathDrawingResourceData();
return data;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.drawing.AbstractDrawingTool#getMouseHandler()
*/
@Override
public IInputHandler getMouseHandler() {
if (theHandler == null) {
theHandler = new PathDrawingHandler();
}
return theHandler;
}
public class PathDrawingHandler extends InputAdapter {
private List<Coordinate> pathList;
private int theLastMouseX;
private int theLastMouseY;
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.ui.input.IInputHandler#handleMouseDown(int,
* int, int)
*/
@Override
public boolean handleMouseDown(int anX, int aY, int button) {
if (button != 1
|| theDrawingLayer.getState() == LayerState.NONE
|| !theDrawingLayer.getCapability(EditableCapability.class)
.isEditable()) {
return false;
}
Cursor cursor = null;
if (theDrawingLayer.getState() == LayerState.ERASING) {
ImageData data = IconUtil.getImageDescriptor(
Activator.getDefault().getBundle(), "eraser_box.gif")
.getImageData();
data.alpha = 255;
cursor = new Cursor(Display.getCurrent(), data, 8, 8);
} else {
cursor = new Cursor(Display.getCurrent(), SWT.CURSOR_HAND);
}
Display.getCurrent().getActiveShell().setCursor(cursor);
cursor.dispose();
if (pathList != null)
pathList.clear();
else
pathList = new ArrayList<Coordinate>();
theLastMouseX = anX;
theLastMouseY = aY;
Coordinate p1 = editor.translateClick(theLastMouseX, theLastMouseY);
pathList.add(p1);
return true;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.ui.input.IInputHandler#handleMouseDownMove(int,
* int, int)
*/
@Override
public boolean handleMouseDownMove(int x, int y, int button) {
if (button != 1
|| theDrawingLayer.getState() == LayerState.NONE
|| !theDrawingLayer.getCapability(EditableCapability.class)
.isEditable()) {
return false;
}
Coordinate p1 = editor.translateClick(theLastMouseX, theLastMouseY);
Coordinate p2 = editor.translateClick(x, y);
if (p1 == null || p2 == null)
return true;
pathList.add(p2);
GeometryFactory gf = new GeometryFactory();
LineString ls = gf.createLineString(new Coordinate[] { p1, p2 });
ls = theDrawingLayer.convertPixels(ls, false);
if (theDrawingLayer.getState() == LayerState.ERASING) {
theDrawingLayer.addTempEraseLine(ls);
} else {
theDrawingLayer.addTempDrawLine(ls);
}
theLastMouseX = x;
theLastMouseY = y;
editor.refresh();
return true;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.ui.input.IInputHandler#handleMouseUp(int, int,
* int)
*/
@Override
public boolean handleMouseUp(int anX, int aY, int button) {
if (button != 1
|| theDrawingLayer.getState() == LayerState.NONE
|| !theDrawingLayer.getCapability(EditableCapability.class)
.isEditable()) {
return false;
}
// change the cursor back on up
Cursor cursor = new Cursor(Display.getCurrent(), SWT.CURSOR_ARROW);
Display.getCurrent().getActiveShell().setCursor(cursor);
cursor.dispose();
theDrawingLayer.resetTemp();
Coordinate[] coords = (Coordinate[]) pathList
.toArray(new Coordinate[pathList.size()]);
GeometryFactory gf = new GeometryFactory();
if (coords.length > 1) {
LineString ls = gf.createLineString(coords);
ls = theDrawingLayer.convertPixels(ls, false);
if (theDrawingLayer.getState() == LayerState.DRAWING
|| theDrawingLayer.getState() == LayerState.ERASING) {
theDrawingLayer.finalizeLine(ls, null);
}
}
editor.refresh();
return true;
}
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.ui.tools.AbstractModalTool#activate()
*/
@Override
public void activate() {
super.activate();
editor.registerMouseHandler(getMouseHandler());
EditableManager.makeEditable(theDrawingLayer, theDrawingLayer
.getCapability(EditableCapability.class).isEditable());
theDrawingLayer.issueRefresh();
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.ui.tools.AbstractModalTool#deactivate()
*/
@Override
public void deactivate() {
super.deactivate();
editor.unregisterMouseHandler(getMouseHandler());
// change the cursor back
if (Display.getCurrent() != null
&& Display.getCurrent().getActiveShell() != null) {
Cursor cursor = new Cursor(Display.getCurrent(), SWT.CURSOR_ARROW);
Display.getCurrent().getActiveShell().setCursor(cursor);
cursor.dispose();
}
theDrawingLayer = null;
}
}