/*******************************************************************************
* Copyright (c) 2012 VMware, Inc.
* 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:
* VMware, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.config.ui.editors;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.forms.AbstractFormPart;
import org.eclipse.ui.forms.IDetailsPage;
import org.eclipse.ui.forms.IFormPart;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
import org.springframework.ide.eclipse.config.graph.parts.ActivityPart;
/**
* This class implements the details portion of the master/details UI pattern.
* Classes that extend {@code AbstractConfigDetailsPart} will display a detailed
* overview of a single element in a Spring configuration file. This class is a
* base only, and clients should consider extending
* {@link AbstractNamespaceDetailsPart} instead.
* @author Leo Dos Santos
* @author Christian Dupuis
* @since 2.0.0
*/
@SuppressWarnings("restriction")
public abstract class AbstractConfigDetailsPart extends AbstractFormPart implements IDetailsPage {
private AbstractConfigMasterPart master;
private AbstractConfigEditor cEditor;
/**
* The toolkit used by the form part.
*/
protected FormToolkit toolkit;
/**
* The details section of the form part.
*/
protected AbstractConfigSectionPart detailsSection;
private IDOMElement input;
/**
* Constructs a details part with a reference to its master part.
*
* @param master the page's master part
*/
public AbstractConfigDetailsPart(AbstractConfigMasterPart master) {
this.master = master;
if (master != null) {
cEditor = master.getConfigEditor();
}
}
/**
* Aligns the header of the given section with the header of the master part
* section. Misalignment can be caused by one header containing toolbar
* icons and the other not.
*
* @param section the section of the details part to be aligned
*/
protected void alignSectionHeaderWithMaster(Section section) {
if (master != null) {
Section masterSection = master.getSection();
if (masterSection != null) {
section.descriptionVerticalSpacing += masterSection.getTextClientHeightDifference();
}
}
}
public void createContents(Composite parent) {
toolkit = getManagedForm().getToolkit();
parent.setLayout(new GridLayout());
if (getMasterViewer() != null) {
updateInput(getMasterViewer().getSelection());
}
createDetailsSection(parent);
}
protected Composite createDetailsClient(Section details) {
details.setLayout(new GridLayout());
details.setLayoutData(new GridData(GridData.FILL_BOTH));
details.setText(getDetailsSectionTitle());
details.setDescription(getDetailsSectionDescription());
Composite detailsClient = toolkit.createComposite(details);
detailsClient.setLayout(new GridLayout());
detailsClient.setLayoutData(new GridData(GridData.FILL_BOTH));
details.setClient(detailsClient);
return detailsClient;
}
/**
* This method is called automatically when the details section is created.
* Client must create and add the content of the details section here, or
* override {@link #createDetailsSection(Composite)} to do nothing.
*
* @param client the parent composite
*/
protected abstract void createDetailsContent(Composite client);
/**
* Creates the details section of the form part. Clients may override if
* necessary.
*
* @param parent the parent composite
*/
protected void createDetailsSection(Composite parent) {
detailsSection = createDetailsSectionPart(getConfigEditor(), getInput(), parent, toolkit);
detailsSection.createContent();
alignSectionHeaderWithMaster(detailsSection.getSection());
}
protected AbstractConfigSectionPart createDetailsSectionPart(AbstractConfigEditor editor, IDOMElement input,
Composite parent, final FormToolkit toolkit) {
final Section details = toolkit.createSection(parent, Section.TITLE_BAR | Section.DESCRIPTION);
return new AbstractConfigSectionPart(cEditor, input, details) {
@Override
public void createContent() {
Composite detailsClient = createDetailsClient(details);
createDetailsContent(detailsClient);
}
};
}
/**
* Returns the the parent editor as an {@link AbstractConfigEditor} object.
*
* @return parent editor instance
*/
public AbstractConfigEditor getConfigEditor() {
return cEditor;
}
/**
* Returns the details section of the form part.
*
* @return details section
*/
public AbstractConfigSectionPart getDetailsSection() {
return detailsSection;
}
/**
* This method is called automatically when the details section is created.
* Clients must return the description of their details section here, or
* override {@link #createDetailsSection(Composite)} to do nothing.
*
* @return details section description
*/
protected abstract String getDetailsSectionDescription();
/**
* This method is called automatically when the details section is created.
* Clients must return the title of their details section here, or override
* {@link #createDetailsSection(Composite)} to do nothing.
*
* @return details section title
*/
protected abstract String getDetailsSectionTitle();
/**
* Returns the XML element that serves as the model for the part.
*
* @return element displayed by the part
*/
public IDOMElement getInput() {
return input;
}
/**
* Returns the master part of the parent form page. May be null.
*
* @return master part of the parent form page
*/
public AbstractConfigMasterPart getMasterPart() {
return master;
}
/**
* Returns the viewer of the master part. May be null.
*
* @return viewer of the master part
*/
protected ColumnViewer getMasterViewer() {
if (master != null) {
return master.getViewer();
}
return null;
}
@Override
public void refresh() {
if (detailsSection != null) {
detailsSection.refresh();
}
super.refresh();
}
public void selectionChanged(IFormPart part, ISelection selection) {
updateInput(selection);
refresh();
}
public void setConfigEditor(AbstractConfigEditor editor) {
cEditor = editor;
}
/**
* Sets a reference to the master part of the parent form page.
*
* @param master the master part of the parent form page
*/
public void setMasterPart(AbstractConfigMasterPart master) {
if (this.master != null) {
this.master.dispose();
}
this.master = master;
if (master != null) {
cEditor = master.getConfigEditor();
}
}
protected void updateInput(ISelection selection) {
IDOMElement oldInput = input;
input = null;
IStructuredSelection sel = (IStructuredSelection) selection;
if (sel != null) {
Object obj = sel.getFirstElement();
if (obj instanceof ActivityPart) {
ActivityPart activity = (ActivityPart) obj;
obj = activity.getModelElement().getInput();
}
if (obj instanceof IDOMElement) {
if (obj != oldInput) {
input = (IDOMElement) obj;
}
else {
input = oldInput;
}
}
}
if (detailsSection != null) {
detailsSection.setFormInput(input);
}
}
}