/*******************************************************************************
* Copyright (c) 2007 Business Objects Software Limited and others.
* All rights reserved.
* This file is 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:
* Business Objects Software Limited - initial API and implementation
*******************************************************************************/
/*
* FeaturesEditor.java
* Created: 27-Mar-07
* By: Rick Cameron
*/
package org.openquark.cal.eclipse.ui.metadataeditor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.DecoratingLabelProvider;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.openquark.cal.compiler.ModuleName;
import org.openquark.cal.compiler.ModuleSourceDefinition;
import org.openquark.cal.compiler.ScopedEntity;
import org.openquark.cal.eclipse.core.CALModelManager;
import org.openquark.cal.eclipse.core.builder.CALBuilder;
import org.openquark.cal.eclipse.ui.CALEclipseUIPlugin;
import org.openquark.cal.eclipse.ui.actions.ActionMessages;
import org.openquark.cal.eclipse.ui.util.ImageLoader;
import org.openquark.cal.eclipse.ui.views.CALModuleContentProvider;
import org.openquark.cal.eclipse.ui.views.HierarchicalNode;
import org.openquark.cal.eclipse.ui.views.ModuleTreeContentProvider;
import org.openquark.cal.eclipse.ui.views.ModuleTreeLabelProvider;
import org.openquark.cal.eclipse.ui.views.ProblemMarkerDecorator;
import org.openquark.cal.services.CALFeatureName;
import org.openquark.cal.services.FeatureName.FeatureType;
import org.openquark.util.UnsafeCast;
/**
* @author Rick Cameron
*
*/
final class FeaturesEditor extends EditorComponent {
private static final int MIN_TREE_HEIGHT = 200;
private static final ImageLoader moduleImageLoader = new ImageLoader (CALEclipseUIPlugin.getImageDescriptor("/icons/nav_module.png")); //$NON-NLS-1$
private static final ImageLoader typeConsImageLoader = new ImageLoader (CALEclipseUIPlugin.getImageDescriptor("/icons/nav_typeconstructor.gif")); //$NON-NLS-1$
private static final ImageLoader typeClassImageLoader = new ImageLoader (CALEclipseUIPlugin.getImageDescriptor("/icons/nav_typeclass.gif")); //$NON-NLS-1$
private static final ImageLoader dataConsImageLoader = new ImageLoader (CALEclipseUIPlugin.getImageDescriptor("/icons/nav_dataconstructor.gif")); //$NON-NLS-1$
private static final ImageLoader functionImageLoader = new ImageLoader (CALEclipseUIPlugin.getImageDescriptor("/icons/nav_function.gif")); //$NON-NLS-1$
private static final LabelProvider calLabelProvider = new LabelProvider () {
/**
* @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
*/
@Override
public String getText (Object element) {
if (element instanceof CALFeatureName) {
CALFeatureName featureName = (CALFeatureName)element;
return featureName.getName ();
}
return super.getText (element);
}
/**
* @see org.eclipse.jface.viewers.LabelProvider#getImage(java.lang.Object)
*/
@Override
public Image getImage (Object element) {
if (element instanceof CALFeatureName) {
CALFeatureName featureName = (CALFeatureName)element;
FeatureType featureType = featureName.getType ();
if (featureType.equals (CALFeatureName.MODULE)) {
return moduleImageLoader.getImage ();
} else if (featureType.equals (CALFeatureName.TYPE_CONSTRUCTOR)) {
return typeConsImageLoader.getImage ();
} else if (featureType.equals (CALFeatureName.TYPE_CLASS)) {
return typeClassImageLoader.getImage ();
} else if (featureType.equals (CALFeatureName.DATA_CONSTRUCTOR)) {
return dataConsImageLoader.getImage ();
} else if (featureType.equals (CALFeatureName.FUNCTION)) {
return functionImageLoader.getImage ();
}
}
return super.getImage (element);
}
};
private static final CALModuleContentProvider moduleContentProvider = new CALModuleContentProvider () {
@Override
public void setShowPrivateElements (boolean value) {
}
@Override
public void setShowModuleHierarchy (boolean value) {
}
@Override
public void setShowElementHierarchy (boolean value) {
}
@Override
public void setLinkWithEditor (boolean value) {
}
@Override
public boolean getShowPrivateElements () {
return true;
}
@Override
public boolean getShowModuleHierarchy () {
return true;
}
@Override
public boolean getShowElementHierarchy () {
return true;
}
@Override
public boolean getLinkWithEditor () {
return false;
}
@Override
public CALModelManager getCALModelManager () {
return CALModelManager.getCALModelManager();
}
};
private Composite panel;
private TreeViewer otherFeatures;
private TableViewer relatedFeatures;
private Button addButton;
private Button removeButton;
private Button upButton;
private Button downButton;
private final ArrayList<CALFeatureName> relatedFeaturesModel = new ArrayList<CALFeatureName> ();
/**
* Constructor FeaturesEditor
*
* @param editorSection
* @param key
* @param title
* @param description
*/
public FeaturesEditor (EditorSection editorSection, String key, String title, String description) {
super (editorSection, key, title, description);
}
/**
* @see org.openquark.cal.eclipse.ui.metadataeditor.EditorComponent#createEditorComponent(org.eclipse.swt.widgets.Composite, org.eclipse.ui.forms.widgets.FormToolkit)
*/
@Override
Control createEditorComponent (Composite parent, FormToolkit formToolkit) {
panel = formToolkit.createComposite (parent);
formToolkit.paintBordersFor (panel);
GridLayoutFactory.swtDefaults ().numColumns (4).applyTo (panel);
Tree otherFeaturesTree = formToolkit.createTree (panel, SWT.H_SCROLL | SWT.V_SCROLL);
GridDataFactory
.fillDefaults ()
.grab (true, true)
.hint (SWT.DEFAULT, MIN_TREE_HEIGHT)
.applyTo (otherFeaturesTree);
otherFeatures = new TreeViewer (otherFeaturesTree);
ILabelProvider labelProvider =
new DecoratingLabelProvider(
new ModuleTreeLabelProvider (moduleContentProvider),
new ProblemMarkerDecorator());
ModuleTreeContentProvider treeContentProvider = makeTreeContentProvider(otherFeatures, labelProvider);
otherFeatures.setContentProvider (treeContentProvider);
otherFeatures.setLabelProvider (labelProvider);
otherFeatures.setSorter(new ViewerSorter());
otherFeatures.setInput (treeContentProvider.getRoot ());
otherFeatures.addSelectionChangedListener (new ISelectionChangedListener () {
public void selectionChanged (SelectionChangedEvent event) {
onOtherFeaturesSelectionChanged ();
}
});
Composite addRemoveBox = formToolkit.createComposite (panel);
GridLayoutFactory.swtDefaults ().numColumns (1).applyTo (addRemoveBox);
addButton = createButton (formToolkit, addRemoveBox, "->", MetadataEditorMessages.AddFeatureButtonToolTip); //$NON-NLS-1$
addButton.addSelectionListener (new SelectionAdapter () {
@Override
public void widgetSelected (SelectionEvent e) {
onAdd ();
}
});
addButton.setEnabled (false);
removeButton = createButton (formToolkit, addRemoveBox, "<-", MetadataEditorMessages.RemoveFeatureButtonToolTip); //$NON-NLS-1$
removeButton.addSelectionListener (new SelectionAdapter () {
@Override
public void widgetSelected (SelectionEvent e) {
onRemove ();
}
});
removeButton.setEnabled (false);
Table relatedFeaturesTable = formToolkit.createTable (panel, SWT.H_SCROLL | SWT.V_SCROLL);
GridDataFactory
.fillDefaults ()
.grab (true, true)
.applyTo (relatedFeaturesTable);
relatedFeatures = new TableViewer (relatedFeaturesTable);
relatedFeatures.setContentProvider (new ArrayContentProvider ());
relatedFeatures.setLabelProvider (calLabelProvider);
relatedFeatures.setInput (relatedFeaturesModel);
relatedFeatures.addSelectionChangedListener (new ISelectionChangedListener () {
public void selectionChanged (SelectionChangedEvent event) {
onRelatedFeaturesSelectionChanged ();
}
});
Composite upDownBox = formToolkit.createComposite (panel);
GridLayoutFactory.swtDefaults ().numColumns (1).applyTo (upDownBox);
upButton = createButton (formToolkit, upDownBox, MetadataEditorMessages.MoveUpItemButtonLabel, MetadataEditorMessages.MoveUpFeatureButtonToolTip);
upButton.addSelectionListener (new SelectionAdapter () {
@Override
public void widgetSelected (SelectionEvent e) {
onUp ();
}
});
upButton.setEnabled (false);
downButton = createButton (formToolkit, upDownBox, MetadataEditorMessages.MoveDownItemButtonLabel, MetadataEditorMessages.MoveDownFeatureButtonToolTip);
downButton.addSelectionListener (new SelectionAdapter () {
@Override
public void widgetSelected (SelectionEvent e) {
onDown ();
}
});
downButton.setEnabled (false);
return panel;
}
/**
* Method enableButtons
*
*/
private void enableButtons () {
onOtherFeaturesSelectionChanged ();
onRelatedFeaturesSelectionChanged ();
}
/**
* Method onOtherFeaturesSelectionChanged
*
*/
private void onOtherFeaturesSelectionChanged () {
CALFeatureName selectedOtherFeature = getSelectedOtherFeature ();
boolean enable = selectedOtherFeature != null && !relatedFeaturesModel.contains (selectedOtherFeature);
addButton.setEnabled (enable);
}
/**
* Method onRelatedFeaturesSelectionChanged
*
*/
private void onRelatedFeaturesSelectionChanged () {
removeButton.setEnabled (getSelectedRelatedFeature () != null);
int selectionIndex = relatedFeatures.getTable ().getSelectionIndex ();
upButton.setEnabled (selectionIndex > 0);
downButton.setEnabled (selectionIndex != -1 && selectionIndex + 1 < relatedFeaturesModel.size ());
}
/**
* Method makeTreeContentProvider
*
* @param treeViewer
*
* @return Returns a ModuleTreeContentProvider
*/
private ModuleTreeContentProvider makeTreeContentProvider (TreeViewer treeViewer, ILabelProvider labelProvider) {
return new ModuleTreeContentProvider (moduleContentProvider, labelProvider, treeViewer) {
@Override
protected void refreshForModule (ModuleSourceDefinition moduleSourceDefinition, boolean updateOnlyModuleName) {
initialize ();
getViewer ().refresh(true);
}
@Override
protected Object[] getRootElements () {
if (getInvisibleRoot () == null) {
initialize ();
}
if (CALBuilder.isEnabled ()) {
if (getInvisibleRoot () instanceof Collection) {
Collection<Object> collection = UnsafeCast.unsafeCast(getInvisibleRoot());
return collection.toArray ();
} else if (getInvisibleRoot () instanceof HierarchicalNode) {
return ((HierarchicalNode)getInvisibleRoot ()).getChildren ();
} else {
return new Object[0];
}
} else {
// CAL Builder is not enabled
setCalBuilderWasEnabled (false);
return new Object[] { ActionMessages.error_calBuilderNotEnabled_message };
}
}
@Override
public void fillLocalPullDown (IMenuManager manager) {
}
@Override
public void fillContextMenu (IMenuManager manager) {
}
};
}
/**
* Method onAdd
*
*/
private void onAdd () {
CALFeatureName featureName = getSelectedOtherFeature ();
if (featureName != null) {
addFeatureName (featureName);
}
}
/**
* Method getSelectedOtherFeature
*
* @return Returns the CALFeatureName selected in the otherFeatures tree, or null
*/
private CALFeatureName getSelectedOtherFeature () {
ISelection selection = otherFeatures.getSelection ();
if (selection instanceof IStructuredSelection) {
IStructuredSelection treeSelection = (IStructuredSelection)selection;
Object firstElement = treeSelection.getFirstElement ();
if (firstElement instanceof ModuleName) {
ModuleName moduleName = (ModuleName)firstElement;
return CALFeatureName.getModuleFeatureName (moduleName);
} else if (firstElement instanceof ScopedEntity) {
ScopedEntity scopedEntity = (ScopedEntity)firstElement;
return CALFeatureName.getScopedEntityFeatureName (scopedEntity);
}
}
return null;
}
/**
* Method addFeatureName
*
* @param featureName
*/
private void addFeatureName (CALFeatureName featureName) {
if (!relatedFeaturesModel.contains (featureName)) {
relatedFeaturesModel.add (featureName);
relatedFeatures.refresh ();
editorChanged ();
}
}
/**
* Method onRemove
*
*/
private void onRemove () {
CALFeatureName selectedRelatedFeature = getSelectedRelatedFeature ();
if (selectedRelatedFeature != null) {
relatedFeaturesModel.remove (selectedRelatedFeature);
relatedFeatures.refresh ();
editorChanged ();
}
}
/**
* Method onUp
*
*/
private void onUp () {
int selectionIndex = relatedFeatures.getTable ().getSelectionIndex ();
if (selectionIndex > 0) {
CALFeatureName featureName = relatedFeaturesModel.remove (selectionIndex);
relatedFeaturesModel.add (selectionIndex - 1, featureName);
relatedFeatures.refresh ();
editorChanged ();
}
}
/**
* Method onDown
*
*/
private void onDown () {
int selectionIndex = relatedFeatures.getTable ().getSelectionIndex ();
if (selectionIndex != -1 && selectionIndex + 1 < relatedFeaturesModel.size ()) {
CALFeatureName featureName = relatedFeaturesModel.remove (selectionIndex);
relatedFeaturesModel.add (selectionIndex + 1, featureName);
relatedFeatures.refresh ();
editorChanged ();
}
}
/**
* Method getSelectedRelatedFeature
*
* @return Returns the {@link CALFeatureName} selected in relatedFeatures
*/
private CALFeatureName getSelectedRelatedFeature () {
ISelection selection = relatedFeatures.getSelection ();
if (selection instanceof IStructuredSelection) {
IStructuredSelection structuredSelection = (IStructuredSelection)selection;
Object firstElement = structuredSelection.getFirstElement ();
if (firstElement instanceof CALFeatureName) {
return (CALFeatureName)firstElement;
}
}
return null;
}
/**
* Method createButton
*
* @param formToolkit
* @param parent
* @param caption
* @param tooltip
*
* @return Returns the Button
*/
private Button createButton (FormToolkit formToolkit, Composite parent, String caption, String tooltip) {
Button button = formToolkit.createButton (parent, caption, SWT.PUSH);
button.setToolTipText (tooltip);
GridDataFactory.fillDefaults ().applyTo (button);
return button;
}
/**
* {@inheritDoc}
*/
@Override
public Control getEditorComponent () {
return panel;
}
/**
* {@inheritDoc}
*/
@Override
public Object getValue () {
return Collections.unmodifiableList (relatedFeaturesModel);
}
/**
* {@inheritDoc}
*/
@Override
public void setValue (Object value) {
List<CALFeatureName> featureNames = UnsafeCast.unsafeCast(value);
relatedFeaturesModel.clear ();
relatedFeaturesModel.addAll (featureNames);
relatedFeatures.refresh ();
enableButtons ();
}
}