Java tutorial
/* * License information at https://github.com/Caltech-IPAC/firefly/blob/master/License.txt */ package edu.caltech.ipac.firefly.visualize; import com.google.gwt.core.client.Scheduler; import com.google.gwt.event.dom.client.MouseDownEvent; import com.google.gwt.event.dom.client.MouseDownHandler; import com.google.gwt.event.dom.client.MouseMoveEvent; import com.google.gwt.event.dom.client.ScrollHandler; import com.google.gwt.event.dom.client.TouchMoveEvent; import com.google.gwt.event.dom.client.TouchStartEvent; import com.google.gwt.event.dom.client.TouchStartHandler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.ui.AbsolutePanel; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FocusPanel; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.RequiresResize; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; import edu.caltech.ipac.firefly.ui.GwtUtil; import edu.caltech.ipac.firefly.ui.PopupPane; import edu.caltech.ipac.firefly.ui.PopupUtil; import edu.caltech.ipac.firefly.util.BrowserUtil; import edu.caltech.ipac.firefly.util.Dimension; import edu.caltech.ipac.firefly.util.WebAssert; import edu.caltech.ipac.firefly.util.event.HasWebEventManager; import edu.caltech.ipac.firefly.util.event.Name; import edu.caltech.ipac.firefly.util.event.PropertyChangeData; import edu.caltech.ipac.firefly.util.event.WebEvent; import edu.caltech.ipac.firefly.util.event.WebEventListener; import edu.caltech.ipac.firefly.util.event.WebEventManager; import edu.caltech.ipac.firefly.visualize.draw.WebLayerItem; import edu.caltech.ipac.firefly.visualize.task.VisTask; import edu.caltech.ipac.visualize.plot.ImagePt; import edu.caltech.ipac.visualize.plot.ImageWorkSpacePt; import edu.caltech.ipac.visualize.plot.Pt; import edu.caltech.ipac.visualize.plot.WorldPt; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.TreeMap; /** * This class is the "gui canvas" that a plot is painted on. It is a * subclass of Composite so it can provide all the paint and graphics * interface into GWT. It also manages multiple plot classes. Currently * This is one of the most key classes in the all vis packages. * * Displaying a plot requires managing multiple layers of widgets. The _masterPanel does this. The _masterPanels sits * in a scroll area. * The layer go from bottom to top in the following order * <ol> * <li>_primaryPlot - the actual fits images</li> * <li>_drawable - the overlays that are drawn on top of the image. This is made of up multiple layers</li> * <li>_mouseMoveArea - this captures mouse move events</li> * </ol> * * @see WebPlot * * @author Trey Roby * @version $Id: WebPlotView.java,v 1.84 2012/05/31 23:12:16 roby Exp $ * * */ public class WebPlotView extends Composite implements Iterable<WebPlot>, Drawable, RequiresResize, HasWebEventManager { public static final String GRID_ID = "GRID_ID"; public static final String DATASET_INFO_CONVERTER = "DATASET_INFO_CONVERTER"; // public static final String EXTENSION_LIST= "EXTENSION_LIST"; // public static final String ACTION_REPORTER= "ACTION_REPORTER"; enum StatusChangeType { ADDED, REMOVED } public static final String PRIMARY_PLOT = "PrimaryPlot"; public static final String TASK = "task-"; private static final int AUTO = 80456; private static int _taskCnt = 0; private ArrayList<WebPlot> _plots = new ArrayList<WebPlot>(10); private Map<WebPlot, ScrollInfo> _scrollInfo = new HashMap<WebPlot, ScrollInfo>(10); private WebPlot _primaryPlot = null; private ScrollInfo _primaryScrollInfo = null; private final Map<String, Object> _attributes = new HashMap<String, Object>(3); private Widget _maskWidget = null; private FocusPanel _mouseMoveArea = new FocusPanel(); private AbsolutePanel _masterPanel = new AbsolutePanel(); private DefaultDrawable _drawable = new DefaultDrawable(); private PVMouse _pvMouse; private final WebEventManager _eventManager = new WebEventManager(); private boolean _lockPlotHint = false; private Map<String, WebLayerItem> _userDrawLayerMap = new TreeMap<String, WebLayerItem>(); private MiniPlotWidget _mpw = null; private boolean _eventsEnabled = true; private List<String> _workingTaskList = new ArrayList<String>(50); private List<ScrollHandler> _scrollHandlerList = new ArrayList<ScrollHandler>(3); private boolean _alive = true; private String drawingSubGroup = null; private List<OverlayPlotView> overlayPlotViews = null; private boolean containsMultiImageFits = false; private boolean containsMultipleCubes = false; private int wcsMarginX = 0; private int wcsMarginY = 0; private int scrollPositionX; private int scrollPositionY; private int scrollWidth = 0; private int scrollHeight = 0; private SimplePanel _scrollingRootPanel = new SimplePanel(); private SimplePanel _scrollViewWindow = new SimplePanel(); /** * Create a new PlotView. This constructor is typically used when the * PlotView <em>will</em> be placed insides a scrolled window. */ public WebPlotView() { initWidgets(); _scrollingRootPanel.addDomHandler(new MouseDownHandler() { public void onMouseDown(MouseDownEvent ev) { if (_mpw != null) _mpw.selectSelf(); } }, MouseDownEvent.getType()); _scrollingRootPanel.addDomHandler(new TouchStartHandler() { public void onTouchStart(TouchStartEvent event) { if (_mpw != null) _mpw.selectSelf(); } }, TouchStartEvent.getType()); } private void initWidgets() { // _scrollingRootPanel.add(_scrollViewWindow, 0, 0); _scrollingRootPanel.add(_scrollViewWindow); _scrollViewWindow.setWidget(_masterPanel); initWidget(_scrollingRootPanel); _pvMouse = new PVMouse(this, _mouseMoveArea); GwtUtil.setStyles(_scrollViewWindow, "margin", "0 auto"); _scrollingRootPanel.addStyleName("web-plot-view-scr"); _mouseMoveArea.addStyleName("event-layer"); _masterPanel.addStyleName("plot-view-master-panel"); _scrollViewWindow.addStyleName("plot-view-scr-view-window"); } public void freeResources() { _pvMouse.freeResources(); if (_plots != null) _plots.clear(); if (_scrollInfo != null) _scrollInfo.clear(); _plots = null; _scrollInfo = null; _eventManager.clear(); _alive = false; } public boolean isAlive() { return _alive; } public void notifyWidgetShowing() { if (_primaryPlot != null) { computePosition(); } } public List<WebPlot> getOverlayPlotList() { if (overlayPlotViews == null || overlayPlotViews.size() == 0) { return new ArrayList<WebPlot>(0); } else { List<WebPlot> opList = new ArrayList<WebPlot>(); WebPlot p; for (OverlayPlotView opv : overlayPlotViews) { p = opv.getMaskPlot(); if (p != null) opList.add(opv.getMaskPlot()); } return opList; } } public List<OverlayPlotView> getOverlayPlotViewList() { return overlayPlotViews; } public void addOverlayPlotView(OverlayPlotView opv) { if (overlayPlotViews == null) overlayPlotViews = new ArrayList<OverlayPlotView>(5); overlayPlotViews.add(opv); } public void removeOverlayPlotView(OverlayPlotView opv) { if (overlayPlotViews != null) overlayPlotViews.remove(opv); } //==================================================================== //------------------- from HasWebEventManager interface //==================================================================== public WebEventManager getEventManager() { return _eventManager; } public void addListener(WebEventListener l) { _eventManager.addListener(l); } public void addListener(Name eventName, WebEventListener l) { _eventManager.addListener(eventName, l); } public void removeListener(WebEventListener l) { _eventManager.removeListener(l); } public void removeListener(Name eventName, WebEventListener l) { _eventManager.removeListener(eventName, l); } public void fireEvent(WebEvent ev) { if (_eventsEnabled) _eventManager.fireEvent(ev); } //=================================================================== //=================================================================== public Widget addDrawingArea(Widget w, boolean highPriority) { return _drawable.addDrawingArea(w, highPriority); } public void removeDrawingArea(Widget w) { _drawable.removeDrawingArea(w); } public void replaceDrawingArea(Widget old, Widget w) { _drawable.replaceDrawingArea(old, w); } public void insertBeforeDrawingArea(Widget before, Widget w) { _drawable.insertBeforeDrawingArea(before, w); } public void insertAfterDrawingArea(Widget after, Widget w) { _drawable.insertAfterDrawingArea(after, w); } public int getDrawingWidth() { return _drawable.getDrawingWidth(); } public int getDrawingHeight() { return _drawable.getDrawingHeight(); } public void setDrawingSubGroup(String drawingSubGroup) { this.drawingSubGroup = drawingSubGroup; } public String getDrawingSubGroup() { return drawingSubGroup; } public void onResize() { recomputeSize(); computeScrollSizes(); recomputeWcsOffsets(); } public void computeScrollSizes() { scrollWidth = _scrollingRootPanel.getOffsetWidth(); scrollHeight = _scrollingRootPanel.getOffsetHeight(); if (_primaryPlot != null) { GwtUtil.setStyle(_scrollViewWindow, "position", "relative"); if (_primaryPlot.getScreenWidth() < scrollWidth) { scrollWidth = _primaryPlot.getScreenWidth(); } if (_primaryPlot.getScreenHeight() < scrollHeight) { scrollHeight = _primaryPlot.getScreenHeight(); } } } public void setMiniPlotWidget(MiniPlotWidget mpw) { _mpw = mpw; } public MiniPlotWidget getMiniPlotWidget() { return _mpw; } public void setAttribute(String key, Object attribute) { _attributes.put(key, attribute); } public void removeAttribute(String key) { _attributes.remove(key); } public Object getAttribute(String key) { return _attributes.get(key); } public boolean containsAttributeKey(String key) { return _attributes.containsKey(key); } public int getUserDrawerLayerListSize() { return _userDrawLayerMap == null ? 0 : _userDrawLayerMap.size(); } public WebLayerItem getItemByID(String id) { return _userDrawLayerMap.get(id); } public WebLayerItem getItemByTitle(String title) { WebLayerItem retval = null; if (title != null) { for (WebLayerItem wl : _userDrawLayerMap.values()) { if (title.equals(wl.getTitle())) { retval = wl; break; } } } return retval; } public Collection<WebLayerItem> getUserDrawerLayerSet() { return Collections.unmodifiableCollection(_userDrawLayerMap.values()); } public void addWebLayerItem(WebLayerItem item) { if (!_userDrawLayerMap.containsKey(item.getID())) { item.setPlotView(this); _userDrawLayerMap.put(item.getID(), item); WebEvent ev = new WebEvent<WebLayerItem>(this, Name.LAYER_ITEM_ADDED, item); fireEvent(ev); } } public void removeWebLayerItem(WebLayerItem item) { if (_userDrawLayerMap.containsKey(item.getID())) { _userDrawLayerMap.remove(item.getID()); WebEvent ev = new WebEvent<WebLayerItem>(this, Name.LAYER_ITEM_REMOVED, item); fireEvent(ev); } } public void setWebLayerItemActive(WebLayerItem item, boolean active) { if (_userDrawLayerMap.containsKey(item.getID())) { if (item.isActive() != active) { item.setActive(active); WebEvent ev = new WebEvent<WebLayerItem>(this, Name.LAYER_ITEM_ACTIVE, item); fireEvent(ev); } } } public String addTask() { _taskCnt++; String task = TASK + _taskCnt; _workingTaskList.add(task); if (_workingTaskList.size() == 1) { WebEvent ev = new WebEvent<WebPlotView>(this, Name.PLOT_TASK_WORKING, this); fireEvent(ev); } return task; } public void removeTask(String id) { if (id != null && _workingTaskList.contains(id)) { _workingTaskList.remove(id); if (_workingTaskList.size() == 0) { WebEvent ev = new WebEvent<WebPlotView>(this, Name.PLOT_TASK_COMPLETE, this); fireEvent(ev); } } } public boolean isTaskWorking() { return _workingTaskList.size() > 0; } public int getScrollX() { return scrollPositionX; } public int getScrollY() { return scrollPositionY; } public ScreenPt getScrollScreenPos() { return new ScreenPt(scrollPositionX, scrollPositionY); } public void refreshDisplay() { if (_primaryPlot != null) { if (getScrollWidth() * getScrollHeight() > 0) { Dimension d = _primaryPlot.getViewPortDimension(); drawTilesInArea(new ScreenPt(_primaryPlot.getViewPortX(), _primaryPlot.getViewPortY()), d.getWidth(), d.getHeight()); } } } private void drawTilesInArea(ScreenPt viewPortLocation, int w, int h) { _primaryPlot.drawTilesInArea(viewPortLocation, w, h); for (WebPlot p : getOverlayPlotList()) { p.drawTilesInArea(viewPortLocation, w, h); } } private void setViewPort(int x, int y, int w, int h) { _primaryPlot.setViewPort(x, y, w, h); for (WebPlot p : getOverlayPlotList()) { p.setViewPort(x, y, w, h); } } public void setTouchScrollingEnabled(boolean enable) { //todo - turn off scrolling I think // _scrollPanel.setTouchScrollingDisabled(!enable); } public int getScrollWidth() { if (scrollWidth == 0) computeScrollSizes(); return scrollWidth; } public int getScrollHeight() { if (scrollHeight == 0) computeScrollSizes(); return scrollHeight; } public void scrollDragEnded() { setScrollXY(getScrollScreenPos()); } public void setScrollXY(int x, int y) { setScrollXY(new ScreenPt(x, y)); } public void setScrollXY(ScreenPt spt) { setScrollXY(spt, false); } public void setScrollXY(ScreenPt spt, boolean dragging) { if (_primaryPlot == null) return; if (spt.getIX() == scrollPositionX && spt.getIY() == scrollPositionY) return; if (getScrollWidth() * getScrollHeight() <= 0) return; int x = spt.getIX(); int y = spt.getIY(); // GwtUtil.getClientLogger().log(Level.INFO, "setScrollXY: sx= "+x+", sy= "+y); int maxX = _primaryPlot.getScreenWidth() - getScrollWidth(); int maxY = _primaryPlot.getScreenHeight() - getScrollHeight(); if (maxX < 0) maxX = 0; if (maxY < 0) maxY = 0; if (x < 0) x = 0; else if (x > maxX) x = maxX; if (y < 0) y = 0; else if (y > maxY) y = maxY; scrollPositionX = x; scrollPositionY = y; // spt= new ScreenPt( x,y); // ViewPortPt vpt= _primaryPlot.getViewPortCoords(spt); // GwtUtil.getClientLogger().log(Level.INFO, "WebPlotView: scrollX="+ x+" scrollY="+y); // scrollPositionX= spt.getIX(); // scrollPositionY= spt.getIY(); // if (!pointInViewPortBounds(vpt) && !dragging) { // recomputeViewPortOnScrollingIfNecessary(); // } computePosition(); // _scrollPanel.setHorizontalScrollPosition(spt.getIX()); // _scrollPanel.setVerticalScrollPosition(spt.getIY()); onScroll(); } private boolean isRecomputeViewPortNecessary() { if (_primaryPlot == null) return false; int sw = getScrollWidth(); int sh = getScrollHeight(); int x = getScrollX(); int y = getScrollY(); Dimension dim = _primaryPlot.getViewPortDimension(); boolean contains = VisUtil.containsRec(_primaryPlot.getViewPortX(), _primaryPlot.getViewPortY(), dim.getWidth(), dim.getHeight(), x, y, sw - 1, sh - 1); return !contains; } public boolean isContainsMultiImageFits() { return containsMultiImageFits; } public void setContainsMultiImageFits(boolean containMultiImageFits) { this.containsMultiImageFits = containMultiImageFits; } public boolean isContainsMultipleCubes() { return containsMultipleCubes; } public void setContainsMultipleCubes(boolean containsMultipleCubes) { this.containsMultipleCubes = containsMultipleCubes; } private void computePosition() { if (_primaryPlot != null) { computePosition(_primaryPlot.getScreenCoords(findCurrentCenterPoint()), false); } } private void computePosition(ScreenPt visibleCenterPt, boolean forceNewViewport) { if (visibleCenterPt == null) return; if (isRecomputeViewPortNecessary() || forceNewViewport) { int screenW = _primaryPlot.getScreenWidth(); int screenH = _primaryPlot.getScreenHeight(); int vpw = getScrollWidth() * 2; int vph = getScrollHeight() * 2; if (vpw > 1500) vpw = Math.max((int) (getScrollWidth() * 1.5), 2700); if (vph > 1400) vph = Math.max((int) (getScrollHeight() * 1.5), 1800); int newVpX; int newVpY; if (vpw > screenW) { vpw = screenW; newVpX = 0; } else { newVpX = visibleCenterPt.getIX() - vpw / 2; if (newVpX < 0) newVpX = 0; else if (newVpX + vpw > screenW) newVpX = screenW - vpw; } if (vph > screenH) { vph = screenH; newVpY = 0; } else { newVpY = visibleCenterPt.getIY() - vph / 2; if (newVpY < 0) newVpY = 0; else if (newVpY + vph > screenH) newVpY = screenH - vph; } if (vpw > 0 && vph > 0) { // todo- only scroll & VP position need to change // GwtUtil.getClientLogger().log(Level.INFO, "VP & Scroll"); setViewPort(newVpX, newVpY, vpw, vph); recomputeSize(); WebEvent ev = new WebEvent<WebPlot>(this, Name.VIEW_PORT_CHANGE, _primaryPlot); Dimension dim = _primaryPlot.getViewPortDimension(); drawTilesInArea(new ScreenPt(newVpX, newVpY), dim.getWidth(), dim.getHeight()); fireEvent(ev); int scrollWidth = getScrollWidth(); int scrollHeight = getScrollHeight(); int x = vpw <= scrollWidth ? 0 : -1 * ((vpw - scrollWidth) / 2); int y = vph <= scrollHeight ? 0 : -1 * ((vph - scrollHeight) / 2); GwtUtil.setStyles(_scrollViewWindow, "left", x + "px", "top", y + "px"); } } else { // todo- only scroll position need to change int sx = getScrollX(); int sy = getScrollY(); int vpX = _primaryPlot.getViewPortX(); int vpY = _primaryPlot.getViewPortY(); int x = vpX - sx; int y = vpY - sy; GwtUtil.setStyles(_scrollViewWindow, "left", x + "px", "top", y + "px"); } } private void recomputeSize() { if (_primaryPlot == null) return; // _masterPanel.setPixelSize(_primaryPlot.getScreenWidth(), _primaryPlot.getScreenHeight() ); // // _mouseMoveArea.setPixelSize(_primaryPlot.getScreenWidth(), _primaryPlot.getScreenHeight() ); // int vpx= _primaryPlot.getViewPortX(); // int vpy= _primaryPlot.getViewPortY(); Dimension dim = _primaryPlot.getViewPortDimension(); _masterPanel.setWidgetPosition(_drawable.getDrawingPanelContainer(), 0, 0); int vpW = dim.getWidth(); int vpH = dim.getHeight(); _scrollViewWindow.setPixelSize(Math.min(vpW, _primaryPlot.getScreenWidth()), Math.min(vpH, _primaryPlot.getScreenHeight())); _masterPanel.setPixelSize(vpW, vpH); _mouseMoveArea.setPixelSize(vpW, vpH); _drawable.setPixelSize(vpW, vpH); } private void setMarginXY(int x, int y) { String lStr = (x == AUTO) ? "auto" : x + "px"; String tStr = (y == AUTO) ? "auto" : y + "px"; GwtUtil.setStyles(_masterPanel, "marginLeft", lStr, "marginRight", "auto", "marginTop", tStr, "cursor", "crosshair"); } // private boolean pointInViewPortBounds(ViewPortPt vpt) { // if (vpt==null) return false; // boolean inBounds= _primaryPlot.pointInViewPort(vpt); // if (inBounds) { // ScreenPt spt= _primaryPlot.getScreenCoords(vpt); // ScreenPt otherExtreme= findOtherExtreme(spt); // inBounds= _primaryPlot.pointInViewPort(otherExtreme); // } // return inBounds; // } // private ScreenPt findOtherExtreme(ScreenPt spt) { // int mw= _primaryPlot.getScreenWidth() - spt.getIX(); // int mh= _primaryPlot.getScreenHeight()- spt.getIY(); // int x= spt.getIX()+ (getScrollWidth() <mw ? getScrollWidth() : mw); // int y= spt.getIY()+ (getScrollHeight()<mh ? getScrollHeight() : mh); // return new ScreenPt(x,y); // } // public FocusPanel getMouseMove() { return _mouseMoveArea; } public Widget getMaskWidget() { return _maskWidget != null ? _maskWidget : this; } public void setMaskWidget(Widget w) { _maskWidget = w; } /** * Add a plot to list of plots this PlotView contains. * This method will fire the PlotViewStatusLister.plotAdded() to * all listeners. * @param p the Plot to add */ public void addPlot(WebPlot p) { addPlot(p, true); } /** * Add a plot to list of plots this PlotView contains. * This method will fire the PlotViewStatusLister.plotAdded() to * all listeners. * @param p the Plot to add * @param makePrimary make the plot just added primary */ public void addPlot(WebPlot p, boolean makePrimary) { addPlot(p, _plots.size(), makePrimary); } public void addPlot(WebPlot p, int idx, boolean makePrimary) { _plots.add(idx, p); _scrollInfo.put(p, new ScrollInfo(p)); p.getPlotGroup().setPlotView(this); if (makePrimary) setPrimaryPlot(p); fireStatusChanged(StatusChangeType.ADDED, p); } /** * Remove a plot from list of plots this PlotView contains. * If the plot to remove is current then the first plot in the list is made * current. This method will fire the PlotViewStatusLister.plotRemoved() to * all listeners. * @param p the Plot to remove * @param freeResources removes any resources this plot is using and calls the server to do the same */ public void removePlot(WebPlot p, boolean freeResources) { p.freeResources(); WebPlot primary = getPrimaryPlot(); p.getPlotGroup().removePlotView(this); _plots.remove(p); ScrollInfo sInfo = _scrollInfo.get(p); if (sInfo != null) { _scrollInfo.remove(p); } if (p == primary) { setPrimaryPlot(_plots.size() > 0 ? _plots.get(0) : null); } fireStatusChanged(StatusChangeType.REMOVED, p); if (freeResources) freePlotResources(p); } private void freePlotResources(WebPlot p) { p.freeResources(); VisTask.getInstance().deletePlot(p); } public void clearAllPlots() { if (_plots.size() > 0) { PropertyChangeData data = new PropertyChangeData(PRIMARY_PLOT, _primaryPlot, null); WebEvent ev = new WebEvent<PropertyChangeData>(this, Name.PRIMARY_PLOT_CHANGE, data); _eventsEnabled = false; WebPlot allPlots[] = _plots.toArray(new WebPlot[_plots.size()]); setPrimaryPlot(allPlots[allPlots.length - 1]); for (WebPlot p : allPlots) removePlot(p, true); _eventsEnabled = true; fireEvent(ev); } } /** * Return the plot that is primary. This is the one that the user sees. * @return Plot the primary Plot */ public WebPlot getPrimaryPlot() { return _primaryPlot; } public boolean contains(WebPlot p) { return p == null ? false : _plots.contains(p); } /** * Return a plot in this <code>PlotView</code>'s list at a given index. * @param i the index of the plot. * @return Plot the plot and the index or null if it is not found. */ public WebPlot getPlot(int i) { WebPlot p = null; if (_plots.size() > i) { p = _plots.get(i); } return p; } /** * Return the number plots in this <code>PlotView</code>'s list. * @return int the number of plots in the list */ public int size() { return _plots.size(); } public int indexOf(WebPlot plot) { return _plots.indexOf(plot); } public WebPlot get(int idx) { return _plots.get(idx); } public void setPrimaryPlot(WebPlot p) { WebPlot old = _primaryPlot; if (old != null && old.isAlive()) old.getPlotGroup().cancelPendingZooms(); PropertyChangeData data = new PropertyChangeData(PRIMARY_PLOT, old, p); WebEvent ev = new WebEvent<PropertyChangeData>(this, Name.PRIMARY_PLOT_CHANGE, data); if (p == null) { _primaryPlot = null; fireEvent(ev); _masterPanel.clear(); _primaryScrollInfo = null; } else if (_plots.contains(p)) { ScrollInfo recallInfo = _scrollInfo.get(p).makeCopy(); _masterPanel.clear(); _masterPanel.add(p.getWidget(), 0, 0); _masterPanel.add(_drawable.getDrawingPanelContainer(), 0, 0); _masterPanel.add(_mouseMoveArea, 0, 0); GwtUtil.setStyle(_mouseMoveArea, "backgroundColor", "transparent"); _primaryPlot = p; _primaryScrollInfo = _scrollInfo.get(p); computeScrollSizes(); computePosition(new ScreenPt(p.getScreenWidth() / 2, p.getScreenHeight() / 2), true); fireEvent(ev); recallScrollPos(recallInfo); AllPlots ap = AllPlots.getInstance(); if (ap.getMiniPlotWidget() == getMiniPlotWidget()) { ap.setSelectedMPW(getMiniPlotWidget(), true, false); } } // else { // } } public void setZoomTo(float zoomLevel, boolean isFullScreen, boolean useDeferredDelay) { if (_primaryPlot != null) { float currZoomFact = _primaryPlot.getZoomFact(); final ImageWorkSpacePt pt = findCurrentCenterPoint(); if (!ZoomUtil.isZoomLevelsMatching(this, currZoomFact, zoomLevel, .0001F)) { _primaryPlot.getPlotGroup().activateDeferredZoom(zoomLevel, isFullScreen, useDeferredDelay, getOverlayPlotList()); Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() { public void execute() { computePosition(_primaryPlot.getScreenCoords(pt), true); if (isWcsSync()) wcsSyncCenter(computeWcsSyncCenter()); else centerOnPoint(pt); } }); } else { if (isWcsSync()) wcsSyncCenter(computeWcsSyncCenter()); else centerOnPoint(pt); } } } public void setZoomByArcsecPerScreenPix(float arcsecPerScreenPix, boolean isFullScreen, boolean useDeferredDelay) { if (_primaryPlot != null) { if (!Float.isNaN(arcsecPerScreenPix)) { setZoomTo((float) _primaryPlot.getImagePixelScaleInArcSec() / arcsecPerScreenPix, isFullScreen, useDeferredDelay); } else { setZoomTo(1F, isFullScreen, useDeferredDelay); } } } // public void setZoomByPlotWidth(int width, boolean isFullScreen, boolean useDeferredDelay) { // if (_primaryPlot!=null) { // if (!Double.isNaN(_primaryPlot.getImagePixelScaleInArcSec())) { // setZoomTo( (float)_primaryPlot.getImagePixelScaleInArcSec() * width, isFullScreen, useDeferredDelay); // } // else { // setZoomTo(1F,isFullScreen, useDeferredDelay); // } // } // } public void showMouseHelp(WebLayerItem item) { if (item.getHelp() != null) { showMouseHelp(item.getHelp()); } } public void showMouseHelp(String text) { showMouseHelp(new HTML(text)); } public void showMouseHelp(Widget w) { w.setWidth("100%"); w.setHeight("100%"); if (getMiniPlotWidget().isExpanded()) { int width = (int) (getOffsetWidth() * .75); PopupUtil.showMinimalMsg(this, w, 5, PopupPane.Align.VISIBLE_BOTTOM, width); } else { int width = getScrollWidth(); PopupUtil.showMinimalMsg(this, w, 5, PopupPane.Align.BOTTOM_CENTER_POPUP_BOTTOM, width); } } /** * return a iterator though all the plots in this <code>PLotView</code>. * @return Iterator iterator through all the plots. */ public Iterator<WebPlot> iterator() { return new PlotIterator(_plots.iterator()); } public List<WebPlot> getPlotList() { return new ArrayList<WebPlot>(_plots); } public boolean isLockedHint() { return _lockPlotHint; } public void setLockedHint(boolean lockPlotHint) { _lockPlotHint = lockPlotHint; WebEvent ev = new WebEvent<Boolean>(this, Name.PLOTVIEW_LOCKED, lockPlotHint); fireEvent(ev); } // ------------------------------------------------------------ // ================= Private / Protected methods ============== // ------------------------------------------------------------ void reconfigure() { computePosition(_primaryPlot.getScreenCoords(findCurrentCenterPoint()), false); } /** * fire the <code>PlotViewStatusListener</code>s. * @param stat a StatusChangeType * @param plot that the event is about. */ protected void fireStatusChanged(StatusChangeType stat, WebPlot plot) { WebEvent ev; switch (stat) { case ADDED: ev = new WebEvent<WebPlot>(this, Name.PLOT_ADDED, plot); fireEvent(ev); break; case REMOVED: ev = new WebEvent<WebPlot>(this, Name.PLOT_REMOVED, plot); fireEvent(ev); break; default: WebAssert.argTst(false, stat + " is unknown to this switch"); } } /** /** * Find the point in the <code>WebPlot</code> that is at the center of * the display. The point returned is in ImageWorkSpacePt coordinates. * We return it in and ImageWorkSpacePt not screen because if the plot * is zoomed the image point will be what we want in the center. * The screen coordinates will be completely different. * @return ImagePt the center point */ public ImageWorkSpacePt findCurrentCenterPoint() { WebPlot plot = getPrimaryPlot(); int screenW = plot.getScreenWidth(); int screenH = plot.getScreenHeight(); int sw = getScrollWidth(); int sh = getScrollHeight(); int cX; int cY; if (screenW < sw) { cX = screenW / 2; } else { int scrollX = getScrollX(); cX = scrollX + sw / 2 - wcsMarginX; } if (screenH < sh) { cY = screenH / 2; } else { int scrollY = getScrollY(); cY = scrollY + sh / 2 - wcsMarginY; } ScreenPt pt = new ScreenPt(cX, cY); return plot.getImageWorkSpaceCoords(pt); } public WorldPt findCurrentCenterWorldPoint() { return _primaryPlot.getWorldCoords(findCurrentCenterPoint()); } //============================================================================== //------------------- Centering Methods ---------------------------------------- //============================================================================== public ScreenPt getWcsMargins() { return new ScreenPt(wcsMarginX, wcsMarginY); } public void clearWcsSync() { int oldMX = wcsMarginX; int oldMY = wcsMarginY; wcsMarginX = 0; wcsMarginY = 0; setMarginXY(AUTO, 0); if (oldMX != 0 || oldMY != 0) { _primaryPlot.refreshWidget(); } } private boolean isWcsSync() { return AllPlots.getInstance().isWCSMatch() && computeWcsSyncCenter() != null; } private WorldPt computeWcsSyncCenter() { AllPlots ap = AllPlots.getInstance(); WorldPt retval = ap.getWcsMatchCenter(); if (retval == null && _primaryPlot.containsAttributeKey(WebPlot.MOVING_TARGET_CTX_ATTR)) { MovingTargetContext mtc = (MovingTargetContext) _primaryPlot .getAttribute(WebPlot.MOVING_TARGET_CTX_ATTR); retval = mtc.getPositionOnImage(); } return retval; } private void recomputeWcsOffsets() { if (isWcsSync()) wcsSyncCenter(computeWcsSyncCenter()); else clearWcsSync(); } /** * TODO * TODO */ private void wcsSyncCenter(WorldPt wcsSyncCenterWP) { boolean clearMargin = true; int oldMX = wcsMarginX; int oldMY = wcsMarginY; if (_primaryPlot != null && wcsSyncCenterWP != null) { int sw = getScrollWidth(); int swCen = sw / 2; int sh = getScrollHeight(); int shCen = sh / 2; if (sw > 0 && sh > 0) { int extraOffsetX; int extraOffsetY; ScreenPt pt = _primaryPlot.getScreenCoords(wcsSyncCenterWP); if (pt != null) { extraOffsetX = swCen - pt.getIX(); extraOffsetY = shCen - pt.getIY(); clearMargin = false; wcsMarginX = extraOffsetX; wcsMarginY = extraOffsetY; setMarginXY(extraOffsetX, extraOffsetY); setScrollXY(0, 0); // setScrollBarsEnabledInternal(false); } else { wcsMarginX = -sw; wcsMarginY = -sh; setMarginXY(-sw, -sh); // setScrollBarsEnabledInternal(false); clearMargin = false; } } if (clearMargin) { clearWcsSync(); } else { if (oldMX != wcsMarginX || oldMY != wcsMarginY) { _primaryPlot.refreshWidget(); } } } } /** * If the plot has the FIXED_TARGET attribute and it is on the image, then center on the fixed target. * Otherwise, center in the middle of the image */ public void smartCenter() { WebPlot p = getPrimaryPlot(); if (p == null) return; if (isWcsSync()) { wcsSyncCenter(computeWcsSyncCenter()); } else if (p.containsAttributeKey(WebPlot.FIXED_TARGET)) { Object o = p.getAttribute(WebPlot.FIXED_TARGET); if (o instanceof ActiveTarget.PosEntry) { ActiveTarget.PosEntry entry = (ActiveTarget.PosEntry) o; ImageWorkSpacePt ipt = p.getImageWorkSpaceCoords(entry.getPt()); if (ipt != null && p.pointInPlot(entry.getPt())) centerOnPoint(ipt); else simpleImageCenter(); } } else { simpleImageCenter(); } } public void centerOnPoint(Pt pt) { if (pt != null && _primaryPlot != null) { ScreenPt spt = _primaryPlot.getScreenCoords(pt); if (spt != null) { setScrollXY(spt.getIX() - getScrollWidth() / 2, spt.getIY() - getScrollHeight() / 2); } } } private void simpleImageCenter() { if (_primaryPlot != null) { int sw = _primaryPlot.getScreenWidth(); int sh = _primaryPlot.getScreenHeight(); int w = getScrollWidth(); int h = getScrollHeight(); setScrollXY((sw - w) / 2, (sh - h) / 2); } } //============================================================================== //------------------- End Centering Methods ---------------------------------------- //============================================================================== public void recallScrollPos() { if (_primaryPlot != null) { recallScrollPos(_scrollInfo.get(_primaryPlot).makeCopy()); } } private void recallScrollPos(ScrollInfo sInfo) { int w = getScrollWidth(); int h = getScrollHeight(); if (sInfo._sWidth == w && sInfo._sHeight == h) { int newH = sInfo._scrollHPos; int newV = sInfo._scrollVPos; setScrollXY(newH, newV); } } public boolean isMultiImageFitsWithSameArea() { if (!containsMultiImageFits) return false; boolean retval = true; int w = _primaryPlot.getImageDataWidth(); int h = _primaryPlot.getImageDataHeight(); ImagePt ic1 = new ImagePt(0, 0); ImagePt ic2 = new ImagePt(w, 0); ImagePt ic3 = new ImagePt(0, h); ImagePt ic4 = new ImagePt(w, h); String projName = _primaryPlot.getProjection().getProjectionName(); WorldPt c1 = _primaryPlot.getWorldCoords(ic1); WorldPt c2 = _primaryPlot.getWorldCoords(ic2); WorldPt c3 = _primaryPlot.getWorldCoords(ic3); WorldPt c4 = _primaryPlot.getWorldCoords(ic4); if (c1 == null || c2 == null || c3 == null || c4 == null) return false; WorldPt iwc1; WorldPt iwc2; WorldPt iwc3; WorldPt iwc4; for (WebPlot p : _plots) { if (w != p.getImageDataWidth() || h != p.getImageDataHeight()) { retval = false; break; } iwc1 = p.getWorldCoords(ic1); iwc2 = p.getWorldCoords(ic2); iwc3 = p.getWorldCoords(ic3); iwc4 = p.getWorldCoords(ic4); if (iwc1 == null || iwc2 == null || iwc3 == null || iwc4 == null) { retval = false; break; } if (!iwc1.equals(c1) || !iwc2.equals(c2) || !iwc3.equals(c3) || !iwc4.equals(c4)) { retval = false; break; } if (!projName.equals(p.getProjection().getProjectionName())) { retval = false; break; } } return retval; } public void addPersistentMouseInfo(MouseInfo info) { _pvMouse.addPersistentMouseInfo(info); } public void removePersistentMouseInfo(MouseInfo info) { _pvMouse.removePersistentMouseInfo(info); } public void grabMouse(MouseInfo info) { _pvMouse.grabMouse(info); } public void releaseMouse(MouseInfo info) { _pvMouse.releaseMouse(info); } public HandlerRegistration addScrollHandler(final ScrollHandler handler) { _scrollHandlerList.add(handler); return new HandlerRegistration() { public void removeHandler() { _scrollHandlerList.remove(handler); } }; } // public void fireMouseLeave(MouseOutEvent ev) { _pvMouse.onMouseOut(ev); } public void fireMouseMove(ScreenPt spt, MouseMoveEvent ev) { _pvMouse.onMouseMove(spt, ev); } // public void fireMouseUp(MouseUpEvent ev) { _pvMouse.onMouseUp(ev); } // public void fireMouseDown(MouseDownEvent ev) { _pvMouse.onMouseDown(ev); } // public void fireMouseEnter(MouseOverEvent ev) { _pvMouse.onMouseOver(ev); } // ------------------------------------------------------------------- // ================== private Inner classes ========================== // ------------------------------------------------------------------- private static class ScrollInfo implements Cloneable { WebPlot _plot; int _sWidth = 0; int _sHeight = 0; int _scrollHPos = 0; int _scrollVPos = 0; public ScrollInfo(WebPlot plot) { _plot = plot; } public ScrollInfo makeCopy() { ScrollInfo si = new ScrollInfo(_plot); si._sWidth = _sWidth; si._sHeight = _sHeight; si._scrollHPos = _scrollHPos; si._scrollVPos = _scrollVPos; return si; } } void enableFocus() { final int scrollX = getScrollX(); final int scrollY = getScrollY(); _mouseMoveArea.setFocus(true); if (BrowserUtil.isIE()) { setScrollXY(scrollX, scrollY); } } void disableTextSelect(boolean disable) { com.google.gwt.dom.client.Element e = RootPanel.get().getElement(); try { disableTextSelectInternal(e, disable); disableTextSelectInternal(_mouseMoveArea.getElement(), disable); } catch (Throwable t) { // ignore } } private native static void disableTextSelectInternal(com.google.gwt.dom.client.Element e, boolean disable)/*-{ if (disable) { e.ondrag = function () { return false; }; e.onselectstart = function () { return false; }; } else { e.ondrag = null; e.onselectstart = null; } }-*/; /** * This PlotIterator implements iterator and is constructed with a * list iterator. It adds functionality on the delete. When a plot is * deleted is makes sure the primary plot index is moved appropriately. */ private class PlotIterator implements Iterator<WebPlot> { Iterator<WebPlot> _iterator; WebPlot _p; public PlotIterator(Iterator<WebPlot> iterator) { _iterator = iterator; } public void remove() { _p.freeResources(); WebPlot primary = getPrimaryPlot(); _p.getPlotGroup().removePlotView(WebPlotView.this); _iterator.remove(); if (_p == primary) { setPrimaryPlot(_plots.get(0)); } } public WebPlot next() { return _iterator.next(); } public boolean hasNext() { return _iterator.hasNext(); } } @Override public String toString() { WebPlot p = getPrimaryPlot(); return p != null ? p.getPlotDesc() : "no plots"; } // ------------------------------------------------------------------- // ================== Public Inner classes ========================== // ------------------------------------------------------------------- public interface MouseAll { void onMouseUp(WebPlotView pv, ScreenPt spt); void onMouseOut(WebPlotView pv); void onMouseDown(WebPlotView pv, ScreenPt spt, MouseDownEvent ev); void onMouseOver(WebPlotView pv, ScreenPt spt); void onMouseMove(WebPlotView pv, ScreenPt spt, MouseMoveEvent ev); void onTouchStart(WebPlotView pv, ScreenPt spt, TouchStartEvent ev); void onTouchMove(WebPlotView pv, ScreenPt spt, TouchMoveEvent ev); void onTouchEnd(WebPlotView pv); void onClick(WebPlotView pv, ScreenPt spt); } public static class DefMouseAll implements MouseAll { public void onMouseUp(WebPlotView pv, ScreenPt spt) { } public void onMouseOut(WebPlotView pv) { } public void onMouseDown(WebPlotView pv, ScreenPt spt, MouseDownEvent ev) { } public void onMouseOver(WebPlotView pv, ScreenPt spt) { } public void onMouseMove(WebPlotView pv, ScreenPt spt, MouseMoveEvent ev) { } public void onTouchStart(WebPlotView pv, ScreenPt spt, TouchStartEvent ev) { } public void onTouchMove(WebPlotView pv, ScreenPt spt, TouchMoveEvent ev) { } public void onTouchEnd(WebPlotView pv) { } public void onClick(WebPlotView pv, ScreenPt spt) { } } public static class MouseInfo { private final MouseAll _handler; private final String _help; private boolean _enableAllPersistent = true; private boolean _enableAllExclusive = false; private boolean _enabled = true; public MouseInfo(MouseAll handler, String help) { _handler = handler; _help = help; } public MouseAll getHandler() { return _handler; } public String getHelp() { return _help; } public boolean getEnableAllPersistent() { return _enableAllPersistent; } public void setEnableAllPersistent(boolean enable) { _enableAllPersistent = enable; } public boolean getEnableAllExclusive() { return _enableAllExclusive; } public void setEnableAllExclusive(boolean enable) { _enableAllExclusive = enable; } public void setEnabled(boolean enabled) { _enabled = enabled; } public boolean isEnabled() { return _enabled; } } private int _lastX = -1; private int _lastY = -1; private int _lastW = -1; private int _lastH = -1; public void onScroll() { int x = getScrollX(); int y = getScrollY(); int w = getScrollWidth(); int h = getScrollHeight(); if (_lastX != x || _lastY != y || _lastW != w || _lastH != h) { //todo - no lose this optimization - i think it needs to be somewhere else now _lastX = x; _lastY = y; _lastW = w; _lastH = h; } if (_primaryScrollInfo != null) { _primaryScrollInfo._sWidth = w; _primaryScrollInfo._sHeight = h; _primaryScrollInfo._scrollHPos = x; _primaryScrollInfo._scrollVPos = y; } for (ScrollHandler handler : _scrollHandlerList) { handler.onScroll(null); } } }