/*******************************************************************************
* Copyright (c) 2010 SAP AG.
* 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:
* Emil Simeonov - initial API and implementation.
* Dimitar Donchev - initial API and implementation.
* Dimitar Tenev - initial API and implementation.
* Nevena Manova - initial API and implementation.
* Georgi Konstantinov - initial API and implementation.
*******************************************************************************/
package org.eclipse.wst.sse.sieditor.ui.v2.sections;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.events.HyperlinkAdapter;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Hyperlink;
import org.eclipse.xsd.XSDPackage;
import org.eclipse.wst.sse.sieditor.model.api.IModelObject;
import org.eclipse.wst.sse.sieditor.model.utils.EmfXsdUtils;
import org.eclipse.wst.sse.sieditor.model.xsd.api.IElement;
import org.eclipse.wst.sse.sieditor.model.xsd.api.IType;
import org.eclipse.wst.sse.sieditor.model.xsd.impl.UnresolvedType;
import org.eclipse.wst.sse.sieditor.ui.Activator;
import org.eclipse.wst.sse.sieditor.ui.i18n.Messages;
import org.eclipse.wst.sse.sieditor.ui.v2.AbstractFormPageController;
import org.eclipse.wst.sse.sieditor.ui.v2.UIConstants;
import org.eclipse.wst.sse.sieditor.ui.v2.common.CarriageReturnListener;
import org.eclipse.wst.sse.sieditor.ui.v2.common.LabeledControl;
import org.eclipse.wst.sse.sieditor.ui.v2.dt.ITypeDisplayer;
import org.eclipse.wst.sse.sieditor.ui.v2.propertyeditor.BaseTypeEditor;
import org.eclipse.wst.sse.sieditor.ui.v2.propertyeditor.ElementTypeEditor;
import org.eclipse.wst.sse.sieditor.ui.v2.sections.elements.ElementNodeDetailsController;
import org.eclipse.wst.sse.sieditor.ui.v2.sections.elements.ElementNodeDetailsController.CardinalityType;
public class ElementDetailsSection extends AbstractDetailsPageSection implements ModifyListener, FocusListener, SelectionListener {
protected LabeledControl<Text> nameControl;
protected LabeledControl<Hyperlink> refControl;
protected LabeledControl<CCombo> cardinalityControl;
protected LabeledControl<Button> nillableControl;
protected ElementTypeEditor typeEditor;
protected BaseTypeEditor baseTypeEditor;
private final Set<Object> dirtyControls;
private final ElementNodeDetailsController detailsController;
final ITypeDisplayer typeDisplayer;
public ElementDetailsSection(final ElementNodeDetailsController detailsController, final FormToolkit toolkit,
final IManagedForm managedForm, final ITypeDisplayer typeDisplayer) {
super(detailsController.getFormPageController(), toolkit, managedForm);
this.detailsController = detailsController;
this.typeDisplayer = typeDisplayer;
dirtyControls = new HashSet<Object>();
typeEditor = new ElementTypeEditor(detailsController, typeDisplayer);
typeEditor.initialize(managedForm);
baseTypeEditor = new BaseTypeEditor((AbstractFormPageController) detailsController.getFormPageController(), typeDisplayer, detailsController);
baseTypeEditor.initialize(managedForm);
typeEditor.setDetailsController(detailsController);
}
@Override
public void createContents(final Composite parent) {
final FormToolkit toolkit = getToolkit();
control = createSection(parent, Messages.ElementDetailsSection_section_title);
final Composite clientComposite = toolkit.createComposite(control);
control.setClient(clientComposite);
setCompositeLayout(clientComposite);
createControls(toolkit, clientComposite);
toolkit.paintBordersFor(clientComposite);
}
@Override
protected int getColumnsCount() {
return 4;
}
private void createControls(final FormToolkit toolkit, final Composite clientComposite) {
refControl = new LabeledControl<Hyperlink>(toolkit, clientComposite, Messages.ElementDetailsSection_0);
refControl.setControl(toolkit.createHyperlink(clientComposite, UIConstants.EMPTY_STRING, SWT.SINGLE));
refControl.getControl().addHyperlinkListener(new HyperlinkAdapter() {
@Override
public void linkActivated(final HyperlinkEvent e) {
final IModelObject modelObject = getNode().getModelObject();
if (modelObject instanceof IElement) {
final IElement element = (IElement) modelObject;
typeDisplayer.showType(element.getType());
}
}
});
GridDataFactory.swtDefaults().grab(true, false).align(SWT.BEGINNING, SWT.CENTER).span(3, 1).applyTo(
refControl.getControl());
nameControl = new LabeledControl<Text>(toolkit, clientComposite, Messages.StructureDetailsSection_name_label);
nameControl.setControl(toolkit.createText(clientComposite, UIConstants.EMPTY_STRING, SWT.SINGLE));
final Text nameText = nameControl.getControl();
nameText.addModifyListener(this);
nameText.addFocusListener(this);
nameText.addKeyListener(CarriageReturnListener.getInstance());
GridDataFactory.swtDefaults().grab(true, false).align(SWT.FILL, SWT.CENTER).span(3, 1).applyTo(nameText);
typeEditor.createControl(toolkit, clientComposite);
baseTypeEditor.createControl(toolkit, clientComposite);
baseTypeEditor.setLinkTitle(Messages.ElementDetailsSection_baseType);
cardinalityControl = new LabeledControl<CCombo>(toolkit, clientComposite,
Messages.ElementDetailsSection_cardinality_label);
cardinalityControl.setControl(Activator.getDefault().createCCombo(toolkit, clientComposite,
SWT.DROP_DOWN | SWT.FLAT | SWT.READ_ONLY));
final CCombo cardinalityComboBox = cardinalityControl.getControl();
cardinalityComboBox.addFocusListener(this);
cardinalityComboBox.addKeyListener(CarriageReturnListener.getInstance());
cardinalityComboBox.add(CardinalityType.ZERO_TO_ONE.toString());
cardinalityComboBox.add(CardinalityType.ONE_TO_ONE.toString());
cardinalityComboBox.add(CardinalityType.ZERO_TO_MANY.toString());
cardinalityComboBox.add(CardinalityType.ONE_TO_MANY.toString());
GridDataFactory.swtDefaults().grab(true, false).span(3, 1).applyTo(cardinalityComboBox);
nillableControl = new LabeledControl<Button>(toolkit, clientComposite, Messages.ElementDetailsSection_nillable_label);
nillableControl.setControl(toolkit.createButton(clientComposite, null, SWT.CHECK));
final Button nillableCheckBox = nillableControl.getControl();
nillableCheckBox.addSelectionListener(this);
nillableCheckBox.addKeyListener(CarriageReturnListener.getInstance());
GridDataFactory.swtDefaults().grab(true, false).span(3, 1).applyTo(nillableCheckBox);
cardinalityComboBox.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(final SelectionEvent e) {
setDirty(cardinalityComboBox, true);
}
@Override
public void widgetDefaultSelected(final SelectionEvent e) {
widgetSelected(e);
}
});
cardinalityComboBox.addFocusListener(new FocusListener() {
@Override
public void focusLost(final FocusEvent e) {
if (isDirty(cardinalityComboBox)) {
detailsController.setCardinality(getSelectedCardinalityType());
setDirty(e.getSource(), false);
dirtyStateChanged();
setDirty(cardinalityComboBox, false);
}
}
@Override
public void focusGained(final FocusEvent e) {
}
});
}
private CardinalityType getSelectedCardinalityType() {
final CCombo cardinalityComboBox = cardinalityControl.getControl();
final int selectedIndex = cardinalityComboBox.getSelectionIndex();
if (selectedIndex >= 0) {
final String text = cardinalityComboBox.getItem(selectedIndex);
for (final CardinalityType ct : CardinalityType.values()) {
if (ct.toString().equals(text)) {
return ct;
}
}
}
return null;
}
private Object refreshInput = null;
@Override
public void refresh() {
cleanDirtyStates();
detailsController.setInput(node);
final boolean isNodeReference = EmfXsdUtils.isReference(node.getModelObject());
final boolean editable = isEditable();
boolean cardinalityEditable = true;
if (!editable) {
cardinalityEditable = isWritableElementReference();
}
if (isNodeReference) {
nameControl.setVisible(false);
refControl.setVisible(true);
refControl.getControl().setText(detailsController.getName());
final IType type = detailsController.getType();
refControl.setEnabled(type != null && !UnresolvedType.instance().equals(type));
refControl.getControl().pack();
refControl.getControl().getParent().redraw();
getProblemDecorator().bind(XSDPackage.Literals.XSD_NAMED_COMPONENT__NAME, refControl);
} else {
refControl.setVisible(false);
nameControl.setVisible(true);
nameControl.getControl().setText(detailsController.getName());
nameControl.getControl().setEditable(editable && detailsController.isNameEditable());
getProblemDecorator().bind(XSDPackage.Literals.XSD_NAMED_COMPONENT__NAME, nameControl);
}
nillableControl.getControl().setSelection(detailsController.isNillable());
final CardinalityType cardinality = detailsController.getCardinality();
if (cardinality != null) {
cardinalityControl.getControl().setText(cardinality.toString());
cardinalityControl.getControl().pack();
cardinalityControl.getControl().getParent().redraw();
} else {
cardinalityControl.getControl().setText(UIConstants.EMPTY_STRING);
}
nillableControl.setEnabled(editable && detailsController.isNillableEditable());
cardinalityControl.setEnabled(cardinalityEditable && detailsController.isCardinalityEditable());
cardinalityControl.setVisible(detailsController.isCardinalityVisible());
nillableControl.setVisible(detailsController.isNillableVisible());
boolean applicable = detailsController.isTypeApplicable();
if (applicable) {
typeEditor.setInput(getNode());
typeEditor.update();
}
typeEditor.setVisible(applicable);
applicable = detailsController.isBaseTypeApplicable();
if (applicable) {
baseTypeEditor.setInput(getNode());
baseTypeEditor.update();
}
baseTypeEditor.setVisible(applicable);
if (refreshInput != null && node != null && refreshInput != node
// &&
// !refreshInput.getClass().getName().equals(node.getClass().getName())
) {
redrawSection();
refreshInput = null;
} else {
refreshInput = node;
}
getProblemDecorator().bind(XSDPackage.Literals.XSD_TYPE_DEFINITION__BASE_TYPE, baseTypeEditor);
getProblemDecorator().bind(XSDPackage.Literals.XSD_TYPE_DEFINITION__ANNOTATION, typeEditor);
getProblemDecorator().updateDecorations();
}
@Override
public boolean isStale() {
if (getModelObject() == null) {
return false;
}
return true;
}
@Override
protected Text getDefaultControl() {
return nameControl.getControl();
}
public void modifyText(final ModifyEvent e) {
final Object source = e.getSource();
if (isDirty(source)) {
return;
}
boolean isDirty = false;
if (source == nameControl.getControl()) {
isDirty = !nameControl.getControl().getText().trim().equals(detailsController.getName());
}
if (isDirty) {
setDirty(source, true);
dirtyStateChanged();
}
}
public void focusGained(final FocusEvent e) {
}
public void focusLost(final FocusEvent e) {
final Object source = e.getSource();
boolean updated = true;
if (source == nameControl.getControl() && isDirty(nameControl.getControl())) {
detailsController.setName(nameControl.getControl().getText().trim());
} else {
updated = false;
}
if (updated) {
setDirty(source, false);
dirtyStateChanged();
}
}
public void widgetDefaultSelected(final SelectionEvent e) {
}
public void widgetSelected(final SelectionEvent e) {
final Object source = e.getSource();
if (source == nillableControl.getControl()) {
detailsController.setNillable(nillableControl.getControl().getSelection());
setDirty(source, false);
dirtyStateChanged();
}
}
private boolean isDirty(final Object control) {
return dirtyControls.contains(control);
}
private void setDirty(final Object control, final boolean dirty) {
if (dirty) {
dirtyControls.add(control);
} else {
dirtyControls.remove(control);
}
}
private void cleanDirtyStates() {
dirtyControls.clear();
}
@Override
public boolean isDirty() {
return !dirtyControls.isEmpty();
}
}