/** * Copyright (c) 2011 committers of YAKINDU and others. * 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: * committers of YAKINDU - initial API and implementation * */ package org.yakindu.sct.ui.editor.editor; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.draw2d.ColorConstants; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.gef.KeyHandler; import org.eclipse.gef.KeyStroke; import org.eclipse.gef.editparts.ZoomManager; import org.eclipse.gef.ui.actions.GEFActionConstants; import org.eclipse.gef.ui.actions.ZoomInAction; import org.eclipse.gef.ui.actions.ZoomOutAction; import org.eclipse.gmf.runtime.common.ui.services.marker.MarkerNavigationService; import org.eclipse.gmf.runtime.diagram.core.preferences.PreferencesHint; import org.eclipse.gmf.runtime.diagram.ui.internal.parts.DiagramGraphicalViewerKeyHandler; import org.eclipse.gmf.runtime.gef.ui.internal.editparts.AnimatableZoomManager; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorSite; import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.help.IWorkbenchHelpSystem; import org.eclipse.ui.ide.IGotoMarker; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; import org.eclipse.xtext.EcoreUtil2; import org.eclipse.xtext.ui.XtextProjectHelper; import org.yakindu.base.base.DomainElement; import org.yakindu.base.xtext.utils.gmf.resource.DirtyStateListener; import org.yakindu.sct.domain.extension.DomainRegistry; import org.yakindu.sct.domain.extension.DomainStatus; import org.yakindu.sct.domain.extension.DomainStatus.Severity; import org.yakindu.sct.domain.extension.IDomain; import org.yakindu.sct.ui.editor.DiagramActivator; import org.yakindu.sct.ui.editor.partitioning.DiagramPartitioningEditor; import org.yakindu.sct.ui.editor.partitioning.DiagramPartitioningUtil; import org.yakindu.sct.ui.editor.proposals.ContentProposalViewerKeyHandler; import org.yakindu.sct.ui.editor.providers.ISCTOutlineFactory; import org.yakindu.sct.ui.editor.utils.HelpContextIds; import org.yakindu.sct.ui.editor.validation.IValidationIssueStore; import org.yakindu.sct.ui.editor.validation.LiveValidationListener; import com.google.inject.Injector; import com.google.inject.Key; /** * @author andreas muelder - Initial contribution and API * @author martin esser */ @SuppressWarnings("restriction") public class StatechartDiagramEditor extends DiagramPartitioningEditor implements IGotoMarker { private static final int INITIAL_PALETTE_SIZE = 175; private static final Font INVALID_DOMAIN_FONT = new Font(null, new FontData("Verdana", 10, SWT.BOLD)); public static final String ID = "org.yakindu.sct.ui.editor.editor.StatechartDiagramEditor"; private KeyHandler keyHandler; private DirtyStateListener domainAdapter; private LiveValidationListener validationListener; private IValidationIssueStore issueStore; public StatechartDiagramEditor() { super(true); } public boolean isEditable() { DomainStatus domainStatus = getDomainStatus(); if (domainStatus == null || domainStatus.getSeverity() == Severity.ERROR) { return false; } return super.isEditable(); } protected DomainStatus getDomainStatus() { EObject element = getDiagram().getElement(); DomainElement domainElement = EcoreUtil2.getContainerOfType(element, DomainElement.class); if (domainElement != null) { DomainStatus domainStatus = DomainRegistry.getDomainStatus(domainElement.getDomainID()); return domainStatus; } return null; }; @Override protected void createBreadcrumbViewer(Composite parent) { DomainStatus domainStatus = getDomainStatus(); if (domainStatus != null && domainStatus.getSeverity() == Severity.ERROR) { createStatusLabel(parent, domainStatus); return; } super.createBreadcrumbViewer(parent); } private void createStatusLabel(Composite parent, DomainStatus domainStatus) { CLabel label = new CLabel(parent, SWT.SHADOW_OUT); label.setFont(INVALID_DOMAIN_FONT); label.setBackground(ColorConstants.white); label.setForeground(ColorConstants.red); label.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJS_ERROR_TSK)); label.setText(domainStatus.getMessage() + " - editor is in readonly mode."); GridDataFactory.fillDefaults().grab(true, false).applyTo(label); parent.pack(true); } protected Object createOutline(Class<?> type) { Injector editorInjector = getEditorInjector(); boolean outlineBindingExists = null != editorInjector.getExistingBinding(Key.get(ISCTOutlineFactory.class)); if (!outlineBindingExists) { // get the GMF default outline return super.getAdapter(type); } ISCTOutlineFactory outlineFactory = editorInjector.getInstance(ISCTOutlineFactory.class); return outlineFactory.createOutline(this); } @Override public void init(IEditorSite site, IEditorInput input) throws PartInitException { super.init(site, input); checkXtextNature(); registerValidationListener(); } protected void registerValidationListener() { issueStore = getEditorInjector().getInstance(IValidationIssueStore.class); issueStore.connect(getDiagram().eResource()); validationListener = getEditorInjector().getInstance(LiveValidationListener.class); validationListener.setResource(getDiagram().eResource()); validationListener.setValidationIssueProcessor(issueStore); getEditingDomain().addResourceSetListener(validationListener); validationListener.scheduleValidation(); } protected Injector getEditorInjector() { IDomain domain = DomainRegistry.getDomain(getDiagram().getElement()); Injector injector = domain.getInjector(IDomain.FEATURE_EDITOR); return injector; } protected void checkXtextNature() { IFileEditorInput editorInput = (IFileEditorInput) getEditorInput(); IProject project = editorInput.getFile().getProject(); if (project != null && !XtextProjectHelper.hasNature(project) && project.isAccessible() && !project.isHidden()) { addNature(project); } } public void addNature(IProject project) { try { IProjectDescription description = project.getDescription(); String[] natures = description.getNatureIds(); String[] newNatures = new String[natures.length + 1]; System.arraycopy(natures, 0, newNatures, 0, natures.length); newNatures[natures.length] = XtextProjectHelper.NATURE_ID; description.setNatureIds(newNatures); project.setDescription(description, null); } catch (CoreException e) { e.printStackTrace(); } } @Override protected TransactionalEditingDomain createEditingDomain() { TransactionalEditingDomain domain = DiagramPartitioningUtil.getSharedDomain(); domainAdapter = new DirtyStateListener(); domain.addResourceSetListener(domainAdapter); return domain; } public void gotoMarker(IMarker marker) { MarkerNavigationService.getInstance().gotoMarker(this, marker); } @Override protected PreferencesHint getPreferencesHint() { return DiagramActivator.DIAGRAM_PREFERENCES_HINT; } @Override protected void createGraphicalViewer(Composite parent) { super.createGraphicalViewer(parent); IWorkbenchHelpSystem helpSystem = PlatformUI.getWorkbench().getHelpSystem(); helpSystem.setHelp(getGraphicalViewer().getControl(), HelpContextIds.SC_EDITOR_GRAPHICAL_VIEWER); } @Override protected void configureGraphicalViewer() { super.configureGraphicalViewer(); disableAnimatedZoom(); createContentProposalViewerKeyHandler(); } // Disable the animated zoom, it is too slow for bigger models protected void disableAnimatedZoom() { AnimatableZoomManager zoomManager = (AnimatableZoomManager) getGraphicalViewer() .getProperty(ZoomManager.class.toString()); zoomManager.setZoomAnimationStyle(ZoomManager.ANIMATE_NEVER); } protected void createContentProposalViewerKeyHandler() { ContentProposalViewerKeyHandler contentProposalHandler = new ContentProposalViewerKeyHandler( getGraphicalViewer()); contentProposalHandler .setParent(new DiagramGraphicalViewerKeyHandler(getGraphicalViewer()).setParent(getKeyHandler())); getGraphicalViewer().setKeyHandler(contentProposalHandler); } /** * Overrides the GMF key handler to fix key binding for zooming and to * remove unused key bindings. */ @Override protected KeyHandler getKeyHandler() { if (keyHandler == null) { keyHandler = new KeyHandler(); registerZoomActions(); // Zoom out - all OS - German and English keyboard layout getKeyHandler().put(KeyStroke.getPressed('-', 0x2d, SWT.MOD1), getActionRegistry().getAction(GEFActionConstants.ZOOM_OUT)); // Zoom in - all OS - English keyboard layout getKeyHandler().put(KeyStroke.getPressed('=', 0x3d, SWT.MOD1), getActionRegistry().getAction(GEFActionConstants.ZOOM_IN)); // Zoom in - Unix - German layout ([CTRL++] propagates char '+') getKeyHandler().put(KeyStroke.getPressed('+', 0x2b, SWT.MOD1), getActionRegistry().getAction(GEFActionConstants.ZOOM_IN)); // Zoom in - Windows - German layout ([CTRL++] propagates char 0x1d) getKeyHandler().put(KeyStroke.getPressed((char) 0x1d, 0x2b, SWT.MOD1), getActionRegistry().getAction(GEFActionConstants.ZOOM_IN)); // Test Error - for AERI testing only // DOWN: stateMask=0x50000 CTRL ALT, keyCode=0x6c 'l', character=0xc // ' ' getKeyHandler().put(KeyStroke.getPressed((char) 0xc, 0x6c, 0x50000), new Action() { @Override public void run() { DiagramActivator.getDefault().getLog() .log(new Status(IStatus.ERROR, DiagramActivator.PLUGIN_ID, "AERI Testing error")); } }); } return keyHandler; } @SuppressWarnings("unchecked") protected void registerZoomActions() { IAction action; action = new ZoomInAction(getZoomManager()); action.setText(""); //$NON-NLS-1$ // no text necessary since this // is not a visible action getActionRegistry().registerAction(action); getSelectionActions().add(action.getId()); action = new ZoomOutAction(getZoomManager()); action.setText(""); //$NON-NLS-1$ // no text necessary since this // is not a visible action getActionRegistry().registerAction(action); getSelectionActions().add(action.getId()); } @Override public String getContributorId() { return ID; } @Override public void dispose() { if (validationListener != null) { validationListener.dispose(); } if (issueStore != null) issueStore.disconnect(getDiagram().eResource()); getEditingDomain().removeResourceSetListener(validationListener); getEditingDomain().removeResourceSetListener(domainAdapter); if (domainAdapter != null) domainAdapter.dispose(); super.dispose(); } @Override protected int getInitialPaletteSize() { return INITIAL_PALETTE_SIZE; } @Override public Object getAdapter(@SuppressWarnings("rawtypes") Class type) { if (IContentOutlinePage.class.equals(type)) { return createOutline(type); } else if (IValidationIssueStore.class.equals(type)) { return issueStore; } return super.getAdapter(type); } }