/*******************************************************************************
* Copyright (c) 2004, 2010 Spring IDE Developers
* 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
*
* Contributors:
* Spring IDE Developers - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.beans.ui.graph.editor;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.SWTGraphics;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.ContextMenuProvider;
import org.eclipse.gef.DefaultEditDomain;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.LayerConstants;
import org.eclipse.gef.RootEditPart;
import org.eclipse.gef.commands.CommandStack;
import org.eclipse.gef.editparts.LayerManager;
import org.eclipse.gef.editparts.ScalableRootEditPart;
import org.eclipse.gef.editparts.ZoomManager;
import org.eclipse.gef.ui.actions.ActionBarContributor;
import org.eclipse.gef.ui.actions.ActionRegistry;
import org.eclipse.gef.ui.actions.PrintAction;
import org.eclipse.gef.ui.actions.UpdateAction;
import org.eclipse.gef.ui.actions.ZoomInAction;
import org.eclipse.gef.ui.actions.ZoomOutAction;
import org.eclipse.gef.ui.parts.GraphicalViewerKeyHandler;
import org.eclipse.gef.ui.parts.ScrollingGraphicalViewer;
import org.eclipse.gef.ui.parts.SelectionSynchronizer;
import org.eclipse.gef.ui.properties.UndoablePropertySheetEntry;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.ImageLoader;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.ISelectionService;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.eclipse.ui.dialogs.SaveAsDialog;
import org.eclipse.ui.part.EditorPart;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
import org.eclipse.ui.views.properties.IPropertySheetPage;
import org.eclipse.ui.views.properties.PropertySheetPage;
import org.springframework.ide.eclipse.beans.core.BeansCorePlugin;
import org.springframework.ide.eclipse.beans.core.internal.model.BeansModelUtils;
import org.springframework.ide.eclipse.beans.core.model.IBean;
import org.springframework.ide.eclipse.beans.core.model.IBeansConfig;
import org.springframework.ide.eclipse.beans.core.model.IBeansConfigSet;
import org.springframework.ide.eclipse.beans.core.model.IBeansProject;
import org.springframework.ide.eclipse.beans.ui.BeansUIPlugin;
import org.springframework.ide.eclipse.beans.ui.graph.BeansGraphPlugin;
import org.springframework.ide.eclipse.beans.ui.graph.actions.ExportAction;
import org.springframework.ide.eclipse.beans.ui.graph.actions.GraphContextMenuProvider;
import org.springframework.ide.eclipse.beans.ui.graph.actions.OpenConfigFile;
import org.springframework.ide.eclipse.beans.ui.graph.actions.OpenJavaType;
import org.springframework.ide.eclipse.beans.ui.graph.model.Graph;
import org.springframework.ide.eclipse.beans.ui.graph.parts.GraphicalPartFactory;
import org.springframework.ide.eclipse.core.SpringCoreUtils;
import org.springframework.ide.eclipse.core.model.IModelChangeListener;
import org.springframework.ide.eclipse.core.model.IModelElement;
import org.springframework.ide.eclipse.core.model.ModelChangeEvent;
import org.springframework.ide.eclipse.core.model.ModelChangeEvent.Type;
/**
* Beans Graph Editor
* @author Torsten Juergeleit
* @author Christian Dupuis
*/
@SuppressWarnings("deprecation")
public class GraphEditor extends EditorPart implements ISelectionListener {
public static final String EDITOR_ID = BeansGraphPlugin.PLUGIN_ID + ".editor";
public static final String CONTEXT_MENU_ID = EDITOR_ID + ".contextmenu";
private GraphOutlinePage outlinePage;
private DefaultEditDomain editDomain;
private GraphicalViewer graphicalViewer;
private ActionRegistry actionRegistry;
private SelectionSynchronizer synchronizer;
private List selectionActions = new ArrayList();
private List propertyActions = new ArrayList();
private IModelChangeListener modelChangeListener = new GraphEditorInputModelChangeListener();
private IPropertyChangeListener propertyChangeListener = new GraphEditorPropertyChangeListener();
private volatile boolean isUpdating = false;
public GraphEditor() {
setEditDomain(new DefaultEditDomain(this));
}
private class GraphEditorPropertyChangeListener implements IPropertyChangeListener {
public void propertyChange(PropertyChangeEvent event) {
if (event.getProperty().equals(BeansUIPlugin.SHOULD_SHOW_EXTENDED_CONTENT_PREFERENCE_ID)
|| event.getProperty().equals(BeansUIPlugin.SHOULD_SHOW_INFRASTRUCTURE_BEANS_PREFERENCE_ID)
|| event.getProperty().equals(BeansUIPlugin.SHOULD_SHOW_INNER_BEANS_PREFERENCE_ID)) {
initializeGraphicalViewer();
}
}
}
/**
* Internal {@link IModelChangeListener} that tracks changes in the graphs underlying element and context and
* triggers a refresh if required.
*/
private class GraphEditorInputModelChangeListener implements IModelChangeListener {
public void elementChanged(ModelChangeEvent event) {
final GraphEditorInput beansInput = (GraphEditorInput) getEditorInput();
boolean refresh = false;
IModelElement changedElement = event.getElement();
IModelElement originalInputElement = BeansCorePlugin.getModel().getElement(beansInput.getElementId());
IModelElement originalContextElement = BeansCorePlugin.getModel().getElement(beansInput.getContextId());
// check if changes appeared in a spring config file
if (changedElement instanceof IBeansConfig) {
IResource changedResource = ((IBeansConfig) changedElement).getElementResource();
refresh = checkForRefresh(changedResource, originalInputElement)
|| checkForRefresh(changedResource, originalContextElement);
}
// changes occured in the project configuration; added config file
// to project or beans config set
else if (changedElement instanceof IBeansProject) {
IBeansProject beansProject = (IBeansProject) changedElement;
refresh = (BeansModelUtils.getChildForElement(beansProject, originalInputElement) != null || BeansModelUtils
.getChildForElement(beansProject, originalContextElement) != null);
}
// most likely a close or remove of project or config
if (!refresh && event.getType() == Type.REMOVED && originalInputElement == null) {
Display display = getSite().getShell().getDisplay();
display.asyncExec(new Runnable() {
public void run() {
closeEditor();
}
});
}
if (refresh) {
Display display = getSite().getShell().getDisplay();
display.asyncExec(new Runnable() {
public void run() {
setInput(beansInput);
initializeGraphicalViewer();
}
});
}
}
private boolean checkForRefresh(IResource changedResource, IModelElement originalInputElement) {
boolean refresh = false;
if (originalInputElement instanceof IBean) {
IResource originalResource = ((IBean) originalInputElement).getElementResource();
refresh = originalResource.equals(changedResource);
}
else if (originalInputElement instanceof IBeansConfig) {
IResource originalResource = ((IBeansConfig) originalInputElement).getElementResource();
refresh = originalResource.equals(changedResource);
}
else if (originalInputElement instanceof IBeansConfigSet) {
refresh = ((IBeansConfigSet) originalInputElement).hasConfig((IFile) changedResource);
}
return refresh;
}
}
@Override
public void setInput(IEditorInput input) {
super.setInput(input);
setPartName(input.getName());
setContentDescription(input.getToolTipText());
}
protected void closeEditor() {
getSite().getPage().closeEditor(this, false);
}
/**
* Sets the contents of the GraphicalViewer after it has been created.
* @see #createGraphicalViewer(Composite)
*/
protected synchronized void initializeGraphicalViewer() {
// check global boolean
if (!isUpdating) {
Job job = new Job("Initialize Beans Graph '" + getPartName() + "'") {
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
if (getEditorInput() instanceof GraphEditorInput && getGraphicalViewer() != null
&& getGraphicalViewer().getControl() != null) {
if (!BeansCorePlugin.getModel().isInitialized()) {
schedule(2500);
return Status.OK_STATUS;
}
final GraphEditorInput input = (GraphEditorInput) getEditorInput();
input.init();
final Graph graph = new Graph(input);
graph.init();
Display.getDefault().asyncExec(new Runnable() {
public void run() {
if (getGraphicalViewer() != null && getGraphicalViewer().getControl() != null) {
setPartName(input.getName());
setContentDescription(input.getToolTipText());
graph.layout(getGraphicalViewer().getControl().getFont());
getGraphicalViewer().setContents(graph);
}
}
});
}
return Status.OK_STATUS;
}
finally {
// reset global boolean value
isUpdating = false;
}
}
};
job.setRule(new BlockingOnSelfSchedulingRule());
job.setPriority(Job.INTERACTIVE);
// set global boolean
isUpdating = true;
job.schedule();
}
}
/**
* Called to configure the graphical viewer before it receives its contents. This is where the root editpart should
* be configured.
*/
@SuppressWarnings({ "unchecked" })
protected void configureGraphicalViewer() {
ScalableRootEditPart root = new ScalableRootEditPart();
List zoomLevels = new ArrayList(3);
zoomLevels.add(ZoomManager.FIT_ALL);
zoomLevels.add(ZoomManager.FIT_WIDTH);
zoomLevels.add(ZoomManager.FIT_HEIGHT);
root.getZoomManager().setZoomLevelContributions(zoomLevels);
IAction zoomIn = new ZoomInAction(root.getZoomManager());
IAction zoomOut = new ZoomOutAction(root.getZoomManager());
getActionRegistry().registerAction(zoomIn);
getActionRegistry().registerAction(zoomOut);
getActionRegistry().registerAction(new ExportAction(this));
getSite().getKeyBindingService().registerAction(zoomIn);
getSite().getKeyBindingService().registerAction(zoomOut);
GraphicalViewer viewer = getGraphicalViewer();
viewer.setRootEditPart(root);
viewer.setKeyHandler(new GraphicalViewerKeyHandler(viewer));
viewer.setEditPartFactory(new GraphicalPartFactory());
viewer.getControl().setBackground(ColorConstants.listBackground);
ContextMenuProvider provider = new GraphContextMenuProvider(viewer, getActionRegistry());
viewer.setContextMenu(provider);
getSite().registerContextMenu(CONTEXT_MENU_ID, provider, viewer);
}
@Override
public Object getAdapter(Class type) {
if (type == IPropertySheetPage.class) {
return getPropertySheetPage();
}
if (type == GraphicalViewer.class) {
return getGraphicalViewer();
}
if (type == ActionRegistry.class) {
return getActionRegistry();
}
if (type == CommandStack.class) {
return getCommandStack();
}
if (type == EditPart.class && getGraphicalViewer() != null) {
return getGraphicalViewer().getRootEditPart();
}
if (type == IFigure.class && getGraphicalViewer() != null) {
return ((GraphicalEditPart) getGraphicalViewer().getRootEditPart()).getFigure();
}
if (type == IContentOutlinePage.class) {
return getOutlinePage();
}
if (type == ZoomManager.class) {
return getZoomManager();
}
return super.getAdapter(type);
}
protected IPropertySheetPage getPropertySheetPage() {
PropertySheetPage page = new PropertySheetPage();
page.setRootEntry(new UndoablePropertySheetEntry(getCommandStack()));
return page;
}
protected ZoomManager getZoomManager() {
return ((ScalableRootEditPart) getGraphicalViewer().getRootEditPart()).getZoomManager();
}
/**
* Returns the outline view.
* @return the overview
*/
protected GraphOutlinePage getOutlinePage() {
if (outlinePage == null && getGraphicalViewer() != null) {
RootEditPart rootEditPart = getGraphicalViewer().getRootEditPart();
if (rootEditPart instanceof ScalableRootEditPart) {
outlinePage = new GraphOutlinePage((ScalableRootEditPart) rootEditPart);
}
}
return outlinePage;
}
/**
* Creates actions for this editor and registers them with the {@link ActionRegistry}.
*/
protected void createActions() {
ActionRegistry registry = getActionRegistry();
IAction action;
action = new ExportAction(this);
registry.registerAction(action);
action = new OpenJavaType(this);
registry.registerAction(action);
action = new OpenConfigFile(this);
registry.registerAction(action);
action = new PrintAction(this);
registry.registerAction(action);
}
/**
* Creates the GraphicalViewer on the specified <code>Composite</code>.
* @param parent the parent composite
*/
protected void createGraphicalViewer(Composite parent) {
GraphicalViewer viewer = new ScrollingGraphicalViewer();
viewer.createControl(parent);
getSite().setSelectionProvider(viewer);
setGraphicalViewer(viewer);
configureGraphicalViewer();
initializeGraphicalViewer();
}
/**
* Realizes the Editor by creating it's Control.
* <P>
* WARNING: This method may or may not be called by the workbench prior to {@link #dispose()}.
* @param parent the parent composite
*/
@Override
public void createPartControl(Composite parent) {
createGraphicalViewer(parent);
}
/**
* @see org.eclipse.ui.IWorkbenchPart#dispose()
*/
@Override
public void dispose() {
getSite().getWorkbenchWindow().getSelectionService().removeSelectionListener(this);
getEditDomain().setActiveTool(null);
getActionRegistry().dispose();
// remove the change listener
BeansCorePlugin.getModel().removeChangeListener(modelChangeListener);
BeansUIPlugin.getDefault().getPluginPreferences().removePropertyChangeListener(propertyChangeListener);
super.dispose();
}
/**
* @see org.eclipse.ui.part.WorkbenchPart#firePropertyChange(int)
*/
@Override
protected void firePropertyChange(int property) {
super.firePropertyChange(property);
updateActions(propertyActions);
}
/**
* Lazily creates and returns the action registry.
* @return the action registry
*/
protected ActionRegistry getActionRegistry() {
if (actionRegistry == null) {
actionRegistry = new ActionRegistry();
}
return actionRegistry;
}
/**
* Returns the command stack.
* @return the command stack
*/
protected CommandStack getCommandStack() {
return getEditDomain().getCommandStack();
}
/**
* Returns the edit domain.
* @return the edit domain
*/
protected DefaultEditDomain getEditDomain() {
return editDomain;
}
/**
* Returns the graphical viewer.
* @return the graphical viewer
*/
public GraphicalViewer getGraphicalViewer() {
return graphicalViewer;
}
/**
* Returns the list of {@link IAction IActions} dependant on property changes in the Editor. These actions should
* implement the {@link UpdateAction} interface so that they can be updated in response to property changes. An
* example is the "Save" action.
* @return the list of property-dependant actions
*/
protected List getPropertyActions() {
return propertyActions;
}
/**
* Returns the list of {@link IAction IActions} dependant on changes in the workbench's {@link ISelectionService}.
* These actions should implement the {@link UpdateAction} interface so that they can be updated in response to
* selection changes. An example is the Delete action.
* @return the list of selection-dependant actions
*/
protected List getSelectionActions() {
return selectionActions;
}
/**
* Returns the selection syncronizer object. The synchronizer can be used to sync the selection of 2 or more
* EditPartViewers.
* @return the syncrhonizer
*/
protected SelectionSynchronizer getSelectionSynchronizer() {
if (synchronizer == null) {
synchronizer = new SelectionSynchronizer();
}
return synchronizer;
}
/**
* Hooks the GraphicalViewer to the rest of the Editor. By default, the viewer is added to the
* SelectionSynchronizer, which can be used to keep 2 or more EditPartViewers in sync. The viewer is also registered
* as the <code>ISelectionProvider</code> for the Editor's PartSite.
*/
protected void hookGraphicalViewer() {
getSelectionSynchronizer().addViewer(getGraphicalViewer());
getSite().setSelectionProvider(getGraphicalViewer());
}
/**
* Sets the site and input for this editor then creates and initializes the actions.
* @see org.eclipse.ui.IEditorPart#init(IEditorSite, IEditorInput)
*/
@Override
public void init(IEditorSite site, IEditorInput input) throws PartInitException {
setSite(site);
setInput(input);
getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(this);
initializeActionRegistry();
// add the model change listener
BeansCorePlugin.getModel().addChangeListener(modelChangeListener);
BeansUIPlugin.getDefault().getPluginPreferences().addPropertyChangeListener(propertyChangeListener);
}
/**
* @see org.eclipse.ui.ISelectionListener#selectionChanged(IWorkbenchPart, ISelection)
*/
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
// If not the active editor, ignore selection changed.
if (this.equals(getSite().getPage().getActiveEditor())) {
updateActions(selectionActions);
}
}
/**
* Initializes the ActionRegistry. This registry may be used by {@link ActionBarContributor ActionBarContributors}
* and/or {@link ContextMenuProvider ContextMenuProviders}.
* <P>
* This method may be called on Editor creation, or lazily the first time {@link #getActionRegistry()} is called.
*/
protected void initializeActionRegistry() {
createActions();
updateActions(propertyActions);
}
/**
* Sets the ActionRegistry for this EditorPart.
* @param registry the registry
*/
protected void setActionRegistry(ActionRegistry registry) {
this.actionRegistry = registry;
}
/**
* Sets the EditDomain for this EditorPart.
* @param ed the domain
*/
protected void setEditDomain(DefaultEditDomain editDomain) {
this.editDomain = editDomain;
}
/**
* @see org.eclipse.ui.IWorkbenchPart#setFocus()
*/
@Override
public void setFocus() {
getGraphicalViewer().getControl().setFocus();
}
/**
* Sets the graphicalViewer for this EditorPart.
* @param viewer the graphical viewer
*/
protected void setGraphicalViewer(GraphicalViewer viewer) {
this.graphicalViewer = viewer;
getEditDomain().addViewer(viewer);
}
/**
* A convenience method for updating a set of actions defined by the given List of action IDs. The actions are found
* by looking up the ID in the {@link #getActionRegistry() action registry}. If the corresponding action is an
* {@link UpdateAction}, it will have its <code>update()</code> method called.
* @param actionIds the list of IDs to update
*/
protected void updateActions(List actionIds) {
ActionRegistry registry = getActionRegistry();
Iterator iter = actionIds.iterator();
while (iter.hasNext()) {
IAction action = registry.getAction(iter.next());
if (action instanceof UpdateAction) {
((UpdateAction) action).update();
}
}
}
@Override
public void doSave(IProgressMonitor monitor) {
}
@Override
public void doSaveAs() {
SaveAsDialog dialog = new SaveAsDialog(getSite().getShell());
dialog.setOriginalName("graph.jpg");
dialog.create();
dialog.setMessage(BeansGraphPlugin.getResourceString("Editor.SaveAsDialog.message"));
dialog.setOriginalName("graph.png");
dialog.open();
IPath path = dialog.getResult();
if (path != null) {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IFile file = workspace.getRoot().getFile(path);
String ext = file.getFileExtension();
if (ext == null || ext.length() == 0
|| !(ext.equalsIgnoreCase("jpg") || ext.equalsIgnoreCase("bmp") || ext.equalsIgnoreCase("png"))) {
ErrorDialog.openError(getSite().getShell(), BeansGraphPlugin
.getResourceString("Editor.SaveError.title"), null, BeansGraphPlugin
.createErrorStatus(BeansGraphPlugin.getResourceString("Editor.SaveAsDialog.error")));
}
else if (ext.equalsIgnoreCase("PNG") && !SpringCoreUtils.isEclipseSameOrNewer(3, 3)) {
ErrorDialog.openError(getSite().getShell(), "Problem",
"Exporting to PNG format is only supported on Eclipse 3.3 or newer", BeansGraphPlugin
.createErrorStatus(BeansGraphPlugin.getResourceString("Editor.SaveAsDialog.error")));
}
else {
if ("PNG".equalsIgnoreCase(ext)) {
saveImage(file, SWT.IMAGE_PNG);
}
else if ("JPG".equalsIgnoreCase(ext) || "JPEG".equalsIgnoreCase(ext)) {
saveImage(file, SWT.IMAGE_JPEG);
}
else if ("BMP".equalsIgnoreCase(ext)) {
saveImage(file, SWT.IMAGE_BMP);
}
}
}
}
/**
* Saves an encoded image from this viewer.
* @param format one of SWT.IMAGE_BMP, SWT.IMAGE_BMP_RLE, SWT.IMAGE_GIF SWT.IMAGE_ICO, SWT.IMAGE_JPEG or
* SWT.IMAGE_PNG
* @return the bytes of an encoded image for the specified viewer
*/
public void saveImage(final IFile file, final int format) {
WorkspaceModifyOperation op = new WorkspaceModifyOperation() {
@Override
public void execute(final IProgressMonitor monitor) throws CoreException {
try {
if (file.exists()) {
file.setContents(new ByteArrayInputStream(createImage(format)), true, false, monitor);
}
else {
file.create(new ByteArrayInputStream(createImage(format)), true, monitor);
}
}
catch (CoreException e) {
ErrorDialog.openError(getSite().getShell(),
BeansGraphPlugin.getResourceString("Editor.SaveError.title"),
BeansGraphPlugin.getResourceString("Editor.SaveError.text"), e.getStatus());
}
}
};
try {
Shell shell = getSite().getWorkbenchWindow().getShell();
new ProgressMonitorDialog(shell).run(false, true, op);
}
catch (InvocationTargetException e) {
BeansGraphPlugin.log(e);
}
catch (InterruptedException e) {
}
}
/**
* Returns the bytes of an encoded image from this viewer.
* @param format one of SWT.IMAGE_BMP, SWT.IMAGE_BMP_RLE, SWT.IMAGE_GIF SWT.IMAGE_ICO, SWT.IMAGE_JPEG or
* SWT.IMAGE_PNG
* @return the bytes of an encoded image for the specified viewer
*/
public byte[] createImage(int format) {
ByteArrayOutputStream result = new ByteArrayOutputStream();
Device device = getGraphicalViewer().getControl().getDisplay();
LayerManager lm = (LayerManager) getGraphicalViewer().getEditPartRegistry().get(LayerManager.ID);
IFigure figure = lm.getLayer(LayerConstants.PRINTABLE_LAYERS);
Rectangle r = figure.getClientArea();
Image image = null;
GC gc = null;
Graphics g = null;
try {
image = new Image(device, r.width, r.height);
gc = new GC(image);
g = new SWTGraphics(gc);
g.translate(r.x * -1, r.y * -1);
figure.paint(g);
ImageLoader imageLoader = new ImageLoader();
imageLoader.data = new ImageData[] { image.getImageData() };
imageLoader.save(result, format);
}
finally {
if (g != null) {
g.dispose();
}
if (gc != null) {
gc.dispose();
}
if (image != null) {
image.dispose();
}
}
return result.toByteArray();
}
public void gotoMarker(IMarker marker) {
}
@Override
public boolean isDirty() {
return false;
}
@Override
public boolean isSaveAsAllowed() {
return true;
}
/**
* {@link ISchedulingRule} implementation that always conflicts with other {@link BlockingOnSelfSchedulingRule}s.
* <p>
* This rule prevents that at no time more than one job with this scheduling rule attached runs. t
*/
private class BlockingOnSelfSchedulingRule implements ISchedulingRule {
/**
* Always returns <code>false</code>.
*/
public boolean contains(ISchedulingRule rule) {
return rule == this;
}
/**
* Returns <code>true</code> if <code>rule</code> is of type {@link BlockingOnSelfSchedulingRule}.
*/
public boolean isConflicting(ISchedulingRule rule) {
return rule instanceof BlockingOnSelfSchedulingRule;
}
}
}