package rocks.inspectit.ui.rcp.ci.form.part;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.ui.forms.IDetailsPage;
import org.eclipse.ui.forms.IFormPart;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.IMessagePrefixProvider;
import org.eclipse.ui.forms.widgets.FormToolkit;
import rocks.inspectit.ui.rcp.InspectIT;
import rocks.inspectit.ui.rcp.InspectITImages;
import rocks.inspectit.ui.rcp.ci.listener.IDetailsModifiedListener;
import rocks.inspectit.ui.rcp.util.RemoveSelection;
import rocks.inspectit.ui.rcp.validation.AbstractValidationManager;
import rocks.inspectit.ui.rcp.validation.IControlValidationListener;
import rocks.inspectit.ui.rcp.validation.ValidationControlDecoration;
import rocks.inspectit.ui.rcp.validation.ValidationState;
/**
* Class holding general functionality for all the details pages that we have.
*
* @param <E>
* Type of element edited in this detail page.
* @author Ivan Senic
*
*/
public abstract class AbstractDetailsPage<E> implements IDetailsPage, IControlValidationListener {
/**
* Managed for part belongs to.
*/
protected IManagedForm managedForm;
/**
* Marker for updating the widgets contents when the selection changes, so that mark dirty is
* only fired when changes occur as result of user interaction.
*/
private boolean updateInProgress;
/**
* {@link IDetailsModifiedListener}.
*/
private final IDetailsModifiedListener<E> detailsModifiedListener;
/**
* Validation manager of the master part.
*/
private final AbstractValidationManager<E> masterValidationManager;
/**
* List of {@link ValidationControlDecoration}s.
*/
private final List<ValidationControlDecoration<?>> validationControlDecorations = new ArrayList<>();
/**
* Listener that marks dirty on any event.
*/
protected Listener markDirtyListener = new Listener() {
@Override
public void handleEvent(Event event) {
if (!updateInProgress) {
commitToInput();
E input = getInput();
if ((null != detailsModifiedListener) && (null != input)) {
detailsModifiedListener.contentModified(input);
}
}
}
};
/**
* Default constructor.
*
* @param detailsModifiedListener
* listener to inform the master block on changes to the input
* @param masterValidationManager
* Validation manager of the master part.
*/
public AbstractDetailsPage(IDetailsModifiedListener<E> detailsModifiedListener, AbstractValidationManager<E> masterValidationManager) {
this.detailsModifiedListener = detailsModifiedListener;
this.masterValidationManager = masterValidationManager;
}
/**
* Returns currently displayed input element or <code>null</code> if one does not exists.
*
* @return Returns currently displayed input element or <code>null</code> if one does not
* exists.
*/
protected abstract E getInput();
/**
* Sets the input from the given selection.
*
* @param selection
* selection
*/
protected abstract void setInput(ISelection selection);
/**
* Updates controls from the input.
*/
protected abstract void updateFromInput();
/**
* Commits changes in page to input.
*/
protected abstract void commitToInput();
/**
* {@inheritDoc}
*/
@Override
public void initialize(IManagedForm form) {
this.managedForm = form;
}
/**
* Updates the display state with validation.
*/
protected void update() {
updateInProgress = true;
updateFromInput();
checkValid(true);
updateInProgress = false;
}
/**
* {@inheritDoc}
*/
@Override
public final void selectionChanged(IFormPart part, ISelection selection) {
if (selection instanceof RemoveSelection) {
boolean currentlyEdited = false;
for (Object element : ((RemoveSelection) selection).toList()) {
if (element == getInput()) {
currentlyEdited = true;
break;
}
}
if (currentlyEdited) {
setInput(StructuredSelection.EMPTY);
update();
}
} else {
setInput(selection);
update();
}
}
/**
* {@inheritDoc}
*/
@Override
public void validationStateChanged(boolean valid, ValidationControlDecoration<?> validationControlDecoration) {
// if we have no input for at the moment we can not notify
if (null == getInput()) {
return;
}
String message = null;
if (!valid) {
IMessagePrefixProvider messagePrefixProvider = managedForm.getMessageManager().getMessagePrefixProvider();
String prefix = messagePrefixProvider.getPrefix(validationControlDecoration.getControl());
// don't append if no prefix can be found
if (!": ".equals(prefix)) {
message = prefix + validationControlDecoration.getDescriptionText();
} else {
message = validationControlDecoration.getDescriptionText();
}
}
ValidationState state = new ValidationState(validationControlDecoration, valid, message);
masterValidationManager.validationStateChanged(getInput(), state);
}
/**
* Validates all {@link ValidationControlDecoration} on the page and returns the current valid
* state.
*
*
* @param executeValidation
* if each {@link #validationControlDecorations} should execute new validation before
* calculating
* @return If the all data in the controls are valid.
*/
protected boolean checkValid(boolean executeValidation) {
boolean valid = true;
for (ValidationControlDecoration<?> decoration : validationControlDecorations) {
if (executeValidation) {
decoration.executeValidation(true);
}
if (!decoration.isValid()) {
valid = false;
if (!executeValidation) {
// if we don't need to execute validation of all decorations, then as soon as we
// find the first invalid we can break out
break;
}
}
}
return valid;
}
/**
* Adds the {@link ValidationControlDecoration} to the list of the decorations. This list is
* used for validating if the complete input on the page is correct.
*
* @param validationControlDecoration
* {@link ValidationControlDecoration}.
*/
protected void addValidationControlDecoration(ValidationControlDecoration<?> validationControlDecoration) {
validationControlDecorations.add(validationControlDecoration);
}
/**
* Creates info icon with given text as tool-tip.
*
* @param parent
* Composite to create on.
* @param toolkit
* {@link FormToolkit} to use.
* @param text
* Information text.
* @return created label
*/
protected Label createInfoLabel(Composite parent, FormToolkit toolkit, String text) {
Label label = toolkit.createLabel(parent, "");
label.setToolTipText(text);
label.setImage(InspectIT.getDefault().getImage(InspectITImages.IMG_INFORMATION));
return label;
}
/**
* {@inheritDoc}
* <p>
* The details page never reports dirty state.
*/
@Override
public boolean isDirty() {
return false;
}
/**
* {@inheritDoc}
*/
@Override
public void commit(boolean onSave) {
}
/**
* {@inheritDoc}
*/
@Override
public boolean isStale() {
return false;
}
/**
* {@inheritDoc}
*/
@Override
public void refresh() {
}
/**
* {@inheritDoc}
*/
@Override
public boolean setFormInput(Object input) {
return false;
}
/**
* {@inheritDoc}
*/
@Override
public void dispose() {
}
}