/** * This file is protected by Copyright. * Please refer to the COPYRIGHT file distributed with this source distribution. * * This file is part of REDHAWK IDE. * * 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 gov.redhawk.ui.editor; import gov.redhawk.internal.ui.ScaPluginImages; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.emf.common.command.BasicCommandStack; import org.eclipse.emf.common.command.Command; import org.eclipse.emf.common.notify.Adapter; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.notify.impl.AdapterImpl; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.edit.domain.EditingDomain; import org.eclipse.emf.edit.domain.IEditingDomainProvider; import org.eclipse.emf.edit.ui.dnd.EditingDomainViewerDropAdapter; import org.eclipse.emf.edit.ui.dnd.LocalTransfer; import org.eclipse.emf.edit.ui.dnd.ViewerDragAdapter; import org.eclipse.emf.edit.ui.provider.UnwrappingSelectionProvider; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.GroupMarker; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.StructuredViewer; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.custom.CCombo; import org.eclipse.swt.custom.CTabFolder; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Link; import org.eclipse.swt.widgets.List; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Spinner; import org.eclipse.swt.widgets.TabFolder; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.Tree; import org.eclipse.ui.IWorkbenchActionConstants; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.dialogs.FilteredTree; import org.eclipse.ui.forms.IFormPart; import org.eclipse.ui.forms.IManagedForm; import org.eclipse.ui.forms.editor.FormPage; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.Hyperlink; import org.eclipse.ui.forms.widgets.ScrolledForm; import org.eclipse.ui.forms.widgets.Section; /** * The Class ScaFormPage. */ public abstract class ScaFormPage extends FormPage implements IMenuListener, IEditingDomainProvider { private boolean fNewStyleHeader = true; private Control fLastFocusControl; private Resource input; private final Adapter listener = new AdapterImpl() { /** * {@inheritDoc} */ @Override public void notifyChanged(final Notification msg) { switch (msg.getFeatureID(Resource.class)) { case Resource.RESOURCE__IS_LOADED: final Resource resource = (Resource) msg.getNotifier(); PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { @Override public void run() { if (!isDisposed()) { refresh(resource); } } }); break; default: break; } } }; private boolean disposed; /** * Instantiates a new sca form page. * * @param editor the editor * @param id the id * @param title the title */ public ScaFormPage(final SCAFormEditor editor, final String id, final String title) { super(editor, id, title); this.fLastFocusControl = null; } /** * @param resource */ protected abstract void refresh(final Resource resource); /** * Instantiates a new sca form page. * * @param editor the editor * @param id the id * @param title the title * @param newStyleHeader the new style header */ public ScaFormPage(final SCAFormEditor editor, final String id, final String title, final boolean newStyleHeader) { this(editor, id, title); this.fNewStyleHeader = newStyleHeader; } /** * @return the common editing domain provided by the parent editor */ @Override public EditingDomain getEditingDomain() { return getEditor().getEditingDomain(); } /** * @return the common command stack provided by the parent editor */ protected BasicCommandStack getCommandStack() { if (getEditingDomain() == null) { return null; } return ((BasicCommandStack) getEditingDomain().getCommandStack()); } /** * Executes a command on the editing domain command stack * * @param command */ protected void execute(final Command command) { getCommandStack().execute(command); } /** * {@inheritDoc} */ @Override protected void createFormContent(final IManagedForm managedForm) { final ScrolledForm form = managedForm.getForm(); final FormToolkit toolkit = managedForm.getToolkit(); // FormColors colors = toolkit.getColors(); // form.getForm().setSeparatorColor(colors.getColor(FormColors.TB_BORDER)); if (this.fNewStyleHeader) { // createNewStyleHeader(form, colors); toolkit.decorateFormHeading(form.getForm()); } final IToolBarManager manager = form.getToolBarManager(); // Create the group marker so that additional buttons can be added to this group // and be to the left of the help button. manager.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)); getEditor().contributeToToolbar(manager); final String href = getHelpResource(); if (href != null) { final Action helpAction = new Action("help") { //$NON-NLS-1$ @Override public void run() { BusyIndicator.showWhile(form.getDisplay(), new Runnable() { @Override public void run() { PlatformUI.getWorkbench().getHelpSystem().displayHelp(href); } }); } }; helpAction.setToolTipText("Help"); helpAction.setImageDescriptor(ScaPluginImages.DESC_HELP); manager.add(helpAction); } // check to see if our form parts are contributing actions final IFormPart[] parts = managedForm.getParts(); for (int i = 0; i < parts.length; i++) { if (parts[i] instanceof IAdaptable) { final IAdaptable adapter = (IAdaptable) parts[i]; final IAction[] actions = (IAction[]) adapter.getAdapter(IAction[].class); if (actions != null) { for (int j = 0; j < actions.length; j++) { form.getToolBarManager().add(actions[j]); } } } } form.updateToolBar(); } /** * {@inheritDoc} */ @Override public SCAFormEditor getEditor() { return (SCAFormEditor) super.getEditor(); } /** * Gets the help resource. * * @return the help resource */ protected String getHelpResource() { return null; } /** * This creates a context menu for the viewer and adds a listener as well * registering the menu for extension. */ protected void createContextMenuFor(final StructuredViewer viewer) { final MenuManager contextMenu = new MenuManager("#PopUp"); contextMenu.add(new Separator("additions")); contextMenu.setRemoveAllWhenShown(true); contextMenu.addMenuListener(this); final Menu menu = contextMenu.createContextMenu(viewer.getControl()); viewer.getControl().setMenu(menu); getSite().registerContextMenu(contextMenu, new UnwrappingSelectionProvider(viewer)); final int dndOperations = DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK; final Transfer[] transfers = new Transfer[] { LocalTransfer.getInstance() }; viewer.addDragSupport(dndOperations, transfers, new ViewerDragAdapter(viewer)); viewer.addDropSupport(dndOperations, transfers, new EditingDomainViewerDropAdapter(getEditingDomain(), viewer)); } /** * Gets the focus control. * * @return the focus control */ protected Control getFocusControl() { final IManagedForm form = getManagedForm(); if (form == null) { return null; } final Control control = form.getForm(); if (control == null || control.isDisposed()) { return null; } final Display display = control.getDisplay(); final Control focusControl = display.getFocusControl(); if (focusControl == null || focusControl.isDisposed()) { return null; } return focusControl; } /** * {@inheritDoc} */ @Override public void createPartControl(final Composite parent) { super.createPartControl(parent); // Dynamically add focus listeners to all the forms children in order // to track the last focus control final IManagedForm managedForm = getManagedForm(); if (managedForm != null) { addLastFocusListeners(managedForm.getForm()); } } /** * Programatically and recursively add focus listeners to the specified * composite and its children that track the last control to have focus * before a page change or the editor lost focus. * * @param composite the composite */ public void addLastFocusListeners(final Composite composite) { final Control[] controls = composite.getChildren(); for (int i = 0; i < controls.length; i++) { final Control control = controls[i]; // Add a focus listener if the control is any one of the below types // Note that the controls listed below represent all the controls // currently in use by all form pages in PDE. In the future, // more controls will have to be added. // Could not add super class categories of controls because it // would include things like tool bars that we don't want to track // focus for. if ((control instanceof Text) || (control instanceof Button) || (control instanceof Combo) || (control instanceof CCombo) || (control instanceof Tree) || (control instanceof Table) || (control instanceof Spinner) || (control instanceof Link) || (control instanceof List) || (control instanceof TabFolder) || (control instanceof CTabFolder) || (control instanceof Hyperlink) || (control instanceof FilteredTree)) { addLastFocusListener(control); } if (control instanceof Composite) { // Recursively add focus listeners to this composites children addLastFocusListeners((Composite) control); } } } /** * Add a focus listener to the specified control that tracks the last * control to have focus on this page. When focus is gained by this control, * it registers itself as the last control to have focus. The last control * to have focus is stored in order to be restored after a page change or * editor loses focus. * * @param control the control */ private void addLastFocusListener(final Control control) { control.addFocusListener(new FocusListener() { @Override public void focusGained(final FocusEvent e) { // NO-OP } @Override public void focusLost(final FocusEvent e) { ScaFormPage.this.fLastFocusControl = control; } }); } /** * Set the focus on the last control to have focus before a page change or * the editor lost focus. */ public void updateFormSelection() { if ((this.fLastFocusControl != null) && !this.fLastFocusControl.isDisposed()) { // Set focus on the control this.fLastFocusControl.setFocus(); // If the control is a Text widget, select its contents if (this.fLastFocusControl instanceof Text) { final Text text = (Text) this.fLastFocusControl; text.setSelection(0, text.getText().length()); } } else { // No focus control set // Fallback on managed form selection mechanism by setting the // focus on this page itself. // The managed form will set focus on the first managed part. // Most likely this will turn out to be a section. // In order for this to work properly, we must override the // sections setFocus() method and set focus on a child control // (preferrably first) that can practically take focus. setFocus(); } } /** * Gets the last focus control. * * @return the last focus control */ public Control getLastFocusControl() { return this.fLastFocusControl; } /** * Sets the last focus control. * * @param control the control */ public void setLastFocusControl(final Control control) { this.fLastFocusControl = control; } /** * Used to align the section client / decriptions of two section headers * horizontally adjacent to each other. The misalignment is caused by one * section header containing toolbar icons and the other not. * * @param masterSection the master section * @param detailsSection the details section */ public void alignSectionHeaders(final Section masterSection, final Section detailsSection) { detailsSection.descriptionVerticalSpacing += masterSection.getTextClientHeightDifference(); } /* * (non-Javadoc) * @seeorg.eclipse.ui.part.EditorPart#doSave(org.eclipse.core.runtime. * IProgressMonitor) */ @Override public final void doSave(final IProgressMonitor monitor) { // nothing to do here - this is handled by the parent editor } /* * (non-Javadoc) * @see org.eclipse.ui.part.EditorPart#doSaveAs() */ @Override public final void doSaveAs() { // nothing to do here - this is handled by the parent editor } /* * (non-Javadoc) * @see org.eclipse.ui.part.EditorPart#isDirty() */ @Override public boolean isDirty() { if (getCommandStack() == null) { return false; } return getCommandStack().isSaveNeeded(); } /* * (non-Javadoc) * @see org.eclipse.ui.part.EditorPart#isSaveAsAllowed() */ @Override public final boolean isSaveAsAllowed() { return false; } /** * {@inheritDoc} */ @Override public void menuAboutToShow(final IMenuManager manager) { // pass the request to show the context menu on to the parent editor getEditor().getActionBarContributor().menuAboutToShow(manager); // final IEditorActionBarContributor contributor = // if (contributor instanceof EditingDomainActionBarContributor) { // ((EditingDomainActionBarContributor) // contributor).menuAboutToShow(manager); // } } protected Resource getInput() { return this.input; } /** * {@inheritDoc} */ @Override public void dispose() { if (isDisposed()) { return; } this.disposed = true; this.removeResourceListener(this.input); super.dispose(); } /** * @since 4.0 */ public boolean isDisposed() { return this.disposed; } /** * This is used by the parent to pass information on the input to be used to * the editor part * * @param selection */ public void setInput(final Resource input) { removeResourceListener(this.input); this.input = input; addResourceListener(this.input); refresh(this.input); } protected void addResourceListener(final Resource resource) { if (resource != null) { resource.eAdapters().add(this.listener); } } protected void removeResourceListener(final Resource resource) { if (resource != null) { resource.eAdapters().remove(this.listener); } } /** * @since 2.1 */ public void setSelection(final ISelection selection) { if (this.isActive()) { this.getEditor().setSelection(selection); } } /** * @since 2.1 */ public ISelection getSelection() { final ISelectionProvider provider = (ISelectionProvider) this.getAdapter(ISelectionProvider.class); if (provider != null) { return provider.getSelection(); } return null; } }