/* * Copyright (c) 2012 European Synchrotron Radiation Facility, * Diamond Light Source Ltd. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package fable.imageviewer.views; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PartInitException; import org.eclipse.ui.part.ViewPart; import fable.framework.toolbox.FableUtils; import fable.framework.toolbox.GridUtils; import fable.imageviewer.component.ActionsProvider; import fable.imageviewer.component.ImageComponent; import fable.imageviewer.component.ImageComponentImage; import fable.imageviewer.component.ImagePlay; import fable.imageviewer.internal.IImagesVarKeys; import fable.imageviewer.internal.ZoomSelection; /** * ImageView implements a view to display an image using the SWT Image widget. * The image is automatically fitted to the window size. The main features are * the display is fast, a variety of controls allow the user to zoom a box, * line, integrated profile or 3d relief, change lookup tables, autoscale or * manually scale the range. The image is treated as a floating point image so * that images scaled between 0 and 1 are displayed correctly. Images can be * loaded using loadFile(FabioFile) or via changeImageData(). * <p> * ImageView allows multiple Views. These are distinguished by the secondary ID. * The secondary ID is typically set by IWorkbenchPage.showView(String viewId, * String secondaryId, int mode). The viewId to use is ImageView.ID. Any plug-in * can call this method and is free to specify the secondary ID as it wishes. * ImageView manages 5 secondary IDs, for the main, zoom, slice1D, slice2D, and * copy views. These IDs are determined by the public fields SECONDARY_ID_xxx. * If you wish to call these views, then you should use these fields by name. * Except for the copy views, there is expected to be zero or one of the others. * On workspace shutdown ImageView hides (i.e. removes) all of the views that it * manages, except the main one with SECONDARY_ID_MAIN. This is to prevent * workspace clutter on restarting the workspace. It does not remove others. * Other plug-ins are responsible for removing ones they created if desired. * When ImageView is first created and does not have an image, then the part * name (name on the tab) is set to the secondary ID + "Image View". This should * help to distinguish empty Image Views created by ImageView and other * plug-ins. Eclipse can create ImageViews with a null secondary ID, e.g. via * Window | Show View. ImageView hides these and creates a new one with * SECONDARY_ID_MAIN to insure all views have a non-null secondary ID. * <p> * New images are typically loaded to the Main view. For example, only the Main * view listens for property change events from the SampleController associated * with the Image Navigator. Loading into the Main view will cause existing * Zoom, Slice1, and Slice2 views to update, depending on if there is a * selection and the current selection mode. That is, if there is a selection * and the current mode is Area then the Zoom view will update, but not Slice1 * or Slice2. Drag and Drop supports dropping on any view. * <p> * ImageView is a large View and is implemented in several classes. The * principal ones are (1) ImageView which manages the usual view things and * holds the values of most of the settings, (2) ImageViewControls which manages * the SWT controls except for the imageCanvas, and (3) ImageViewImage which * manages the imageCanvas and things, such as selections, related to it. * <p> * <b>Dependencies</b> : <br> * FabioFile - for loading FabioFiles <br> * ZoomLineView - for plotting lines and integrated profiles<br> * <br> * The image can be viewed in 8 orientations. These orientations are associated * with the TotalCrys o parameters (o11, o12, o21, o22). The parameters that * result in an image oriented as it would be looking at the detector in the * direction of the beam are the o parameters to specify in other Fable * software, such as ImageD11. <br> * <br> * The coordinate origin can be selected as TL=(0,0) (typical image * coordinates), TR=(0,0), BR=(0,0) (TotalCrys coordinates), and BL=(0,0) (usual * xy coordinate system). They can also be specified as custom. The only place * the coordinates appear is in the display of the mouse position. Note that the * coordinate system and the image orientation may be specified independently. <br> * <br> * The TotalCryst project (cf. * http://fable.wiki.sourceforge.net/space/showimage/Geometry_version_1.0.2.pdf) * defines the coordinate system as follows: <br> * (o) Horizontal axis as Y with zero on the right and positive to the left<br> * (o) Vertical axis as Z with zero at the bottom and positive up.<br> * * @author Andy Gotz (ESRF), Ken Evans (APS) * */ public class ImageView extends ViewPart implements IImagesVarKeys, ActionsProvider { /** * Plug-in ID. */ public static final String ID = "fable.imageviewer.views.ImageView"; /** * The object which does the work, can be used in different view parts. */ private ImageComponent imageComponent; /* * (non-Javadoc) * * @see * org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets * .Composite) */ @Override public void createPartControl(Composite parent) { // Trap any view created with a secondary ID of null. These are created // by Eclipse e.g. via Window | Show View. String secondaryId = getSecondaryId(); if (secondaryId == null) { // Hide this one and create one with a known secondary ID of // SECONDARY_ID_MAIN. We need to do it asynchronously as we can't // close the view until the create code has finished Display.getDefault().asyncExec(new Runnable() { @Override public void run() { IWorkbenchPage page = getViewSite().getPage(); if (page == null) { return; } // Destroy the one with null secondary ID page.hideView(ImageView.this); // Open one with SECONDARY_ID_MAIN try { page.showView(ImageView.ID, ImageComponent.SECONDARY_ID_MAIN, IWorkbenchPage.VIEW_CREATE); } catch (PartInitException ex) { FableUtils.excMsg(this, "Error creating view with known secondary ID", ex); } } }); // Return now as we're done with the null secondary-id view return; } // Set the part name using the secondary ID setPartName(secondaryId + " Image View"); this.imageComponent = new ImageComponent(this); imageComponent.createPartControl(parent); GridUtils.removeMargins(parent); // Save first main view as main view if (secondaryId.equals(ImageComponent.SECONDARY_ID_MAIN)) { ImagePlay.setView(imageComponent); } } /* * (non-Javadoc) * * @see org.eclipse.ui.part.WorkbenchPart#setFocus() */ @Override public void setFocus() { if (imageComponent!=null) imageComponent.setFocus(); } /* * (non-Javadoc) * * @see org.eclipse.ui.part.WorkbenchPart#dispose() */ @Override public void dispose() { if (imageComponent!=null) imageComponent.dispose(); } /** * @return the secondary ID of this instance. */ public String getSecondaryId() { String id2 = null; try { id2 = getViewSite().getSecondaryId(); } catch (Exception ex) { // Do nothing } return id2; } public ImageComponentImage getImage() { return imageComponent.getImage(); } public void setPartName(final String name) { super.setPartName(name); } public void transferSelectedSettings(ImageComponent iv) { imageComponent.transferSelectedSettings(iv); } public ImageComponent getImageComponent() { return imageComponent; } @Override public IActionBars getActionBars() { return getViewSite().getActionBars(); } public void setZoomSelection(ZoomSelection area) { getImageComponent().setZoomSelection(area); } }