blob: 28131c47287bf2df99c1e3a52995f3f548f8d106 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2010 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.texteditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.PlatformUI;
/**
* Capable of handling input elements that have an associated status with them.
* @since 2.0
*/
public class StatusTextEditor extends AbstractTextEditor {
/** The root composite of this editor */
private Composite fParent;
/** The layout used to manage the regular and the status page */
private StackLayout fStackLayout;
/** The root composite for the regular page */
private Composite fDefaultComposite;
/** The status page */
private Control fStatusControl;
/** {@link #setFocus()} is still running */
private boolean setFocusIsRunning;
// No .options for plugin yet
private static final boolean DEBUG = false;
/*
* @see org.eclipse.ui.texteditor.AbstractTextEditor.createPartControl(Composite)
*/
@Override
public void createPartControl(Composite parent) {
fParent= new Composite(parent, SWT.NONE);
fStackLayout= new StackLayout();
fParent.setLayout(fStackLayout);
fDefaultComposite= new Composite(fParent, SWT.NONE);
fDefaultComposite.setLayout(new FillLayout());
super.createPartControl(fDefaultComposite);
updatePartControl(getEditorInput());
}
/**
* Checks if the status of the given input is OK. If not the
* status control is shown rather than the default control.
*
* @param input the input whose status is checked
*/
public void updatePartControl(IEditorInput input) {
final String where = "updatePartControl"; //$NON-NLS-1$
if (setFocusIsRunning) {
trace(where, "ERROR: trying to call update while processing focus", fStatusControl); //$NON-NLS-1$
} else {
trace(where, "START", fStatusControl); //$NON-NLS-1$
}
boolean restoreFocus= false;
if (fStatusControl != null) {
if (!fStatusControl.isDisposed()) {
restoreFocus= containsFocus(fStatusControl);
}
fStatusControl.dispose();
trace(where, "status control disposed", fStatusControl); //$NON-NLS-1$
fStatusControl= null;
}
Control front= null;
if (fParent != null && input != null) {
if (getDocumentProvider() instanceof IDocumentProviderExtension) {
IDocumentProviderExtension extension= (IDocumentProviderExtension) getDocumentProvider();
IStatus status= extension.getStatus(input);
if (!isErrorStatus(status)) {
front= fDefaultComposite;
} else {
fStatusControl= createStatusControl(fParent, status);
trace(where, "status control created", fStatusControl); //$NON-NLS-1$
front= fStatusControl;
}
}
}
if (fStackLayout.topControl != front) {
fStackLayout.topControl= front;
fParent.layout();
updateStatusFields();
}
if (restoreFocus && fStatusControl != null && !containsFocus(fStatusControl)) {
fParent.setFocus();
}
trace(where, "END", fStatusControl); //$NON-NLS-1$
}
private boolean containsFocus(Control control) {
Control focusControl= control.getDisplay().getFocusControl();
if (focusControl != null) {
focusControl= focusControl.getParent();
while (focusControl != fParent && focusControl != null && !(focusControl instanceof Shell)) {
focusControl= focusControl.getParent();
}
}
return focusControl == fParent;
}
@Override
public void setFocus() {
final String where = "setFocus"; //$NON-NLS-1$
if (setFocusIsRunning) {
trace(where, "ERROR: trying to call setFocus while processing focus", fStatusControl); //$NON-NLS-1$
} else {
trace(where, "START", fStatusControl); //$NON-NLS-1$
}
setFocusIsRunning = true;
if (fStatusControl != null && !fStatusControl.isDisposed()) {
/* even if the control does not really take focus, we still have to set it
* to fulfill the contract and to make e.g. Ctrl+PageUp/Down work. */
fStatusControl.setFocus();
} else {
super.setFocus();
}
setFocusIsRunning = false;
trace(where, "END", fStatusControl); //$NON-NLS-1$
}
@Override
public boolean validateEditorInputState() {
if (!super.validateEditorInputState())
return false;
if (getDocumentProvider() instanceof IDocumentProviderExtension) {
IDocumentProviderExtension extension= (IDocumentProviderExtension)getDocumentProvider();
IStatus status= extension.getStatus(getEditorInput());
return !isErrorStatus(status) && status.getSeverity() != IStatus.CANCEL;
}
return true;
}
/**
* Returns whether the given status indicates an error. Subclasses may override.
*
* @param status the status to be checked
* @return <code>true</code> if the status indicates an error, <code>false</code> otherwise\
* @since 3.0
*/
protected boolean isErrorStatus(IStatus status) {
return status != null && status.getSeverity() == IStatus.ERROR;
}
/**
* Creates the status control for the given status.
* May be overridden by subclasses.
*
* @param parent the parent control
* @param status the status
* @return the new status control
*/
protected Control createStatusControl(Composite parent, IStatus status) {
return createInfoForm(parent, status);
}
/**
* Helper to get rid of deprecation warnings.
*
* @param parent the parent
* @param status the status
* @return the control
* @since 3.5
* @deprecated As of 3.5
*/
@Deprecated
private Control createInfoForm(Composite parent, IStatus status) {
InfoForm infoForm= new InfoForm(parent);
infoForm.setHeaderText(getStatusHeader(status));
infoForm.setBannerText(getStatusBanner(status));
infoForm.setInfo(getStatusMessage(status));
return infoForm.getControl();
}
/**
* Returns a header for the given status
*
* @param status the status whose message is returned
* @return a header for the given status
*/
protected String getStatusHeader(IStatus status) {
return ""; //$NON-NLS-1$
}
/**
* Returns a banner for the given status.
*
* @param status the status whose message is returned
* @return a banner for the given status
*/
protected String getStatusBanner(IStatus status) {
return ""; //$NON-NLS-1$
}
/**
* Returns a message for the given status.
*
* @param status the status whose message is returned
* @return a message for the given status
*/
protected String getStatusMessage(IStatus status) {
return status.getMessage();
}
@Override
protected void updateStatusField(String category) {
IDocumentProvider provider= getDocumentProvider();
if (provider instanceof IDocumentProviderExtension) {
IDocumentProviderExtension extension= (IDocumentProviderExtension) provider;
IStatus status= extension.getStatus(getEditorInput());
if (isErrorStatus(status)) {
IStatusField field= getStatusField(category);
if (field != null) {
field.setText(fErrorLabel);
return;
}
}
}
super.updateStatusField(category);
}
@Override
protected void doSetInput(IEditorInput input) throws CoreException {
super.doSetInput(input);
updatePartControl();
}
@Override
public void doRevertToSaved() {
// http://dev.eclipse.org/bugs/show_bug.cgi?id=19014
super.doRevertToSaved();
updatePartControl();
}
@Override
protected void sanityCheckState(IEditorInput input) {
// http://dev.eclipse.org/bugs/show_bug.cgi?id=19014
super.sanityCheckState(input);
if (!setFocusIsRunning) {
updatePartControl();
} else {
trace("sanityCheck", "delaying update", fStatusControl); //$NON-NLS-1$ //$NON-NLS-2$
PlatformUI.getWorkbench().getDisplay().asyncExec(() -> {
trace("sanityCheck", "incoming update", fStatusControl); //$NON-NLS-1$ //$NON-NLS-2$
updatePartControl();
});
}
}
@Override
protected void handleEditorInputChanged() {
super.handleEditorInputChanged();
updatePartControl();
}
@Override
protected void handleElementContentReplaced() {
super.handleElementContentReplaced();
updatePartControl();
}
private void updatePartControl() {
if (fParent != null && !fParent.isDisposed()) {
updatePartControl(getEditorInput());
}
}
private static void trace(String where, String what, Control o) {
if (!DEBUG) {
return;
}
String id;
if (o == null) {
id = "null"; //$NON-NLS-1$
} else {
id = System.identityHashCode(o) + (o.isDisposed() ? "<disposed!>" : ""); //$NON-NLS-1$ //$NON-NLS-2$
}
System.out.println(where + " |" + id + "| " + what); //$NON-NLS-1$//$NON-NLS-2$
}
}