package org.objectstyle.wolips.componenteditor.inspector;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.beans.BeansObservables;
import org.eclipse.core.databinding.validation.IValidator;
import org.eclipse.core.databinding.validation.ValidationStatus;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ColumnViewerEditor;
import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent;
import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.TableViewerEditor;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.editors.text.TextEditor;
import org.objectstyle.wolips.baseforplugins.util.ComparisonUtils;
import org.objectstyle.wolips.baseforuiplugins.utils.WOTextCellEditor;
import org.objectstyle.wolips.bindings.api.IApiBinding;
import org.objectstyle.wolips.bindings.api.Wo;
import org.objectstyle.wolips.bindings.wod.BindingValueKeyPath;
import org.objectstyle.wolips.bindings.wod.IWodBinding;
import org.objectstyle.wolips.bindings.wod.IWodElement;
import org.objectstyle.wolips.bindings.wod.WodProblem;
import org.objectstyle.wolips.wodclipse.core.completion.WodCompletionUtils;
import org.objectstyle.wolips.wodclipse.core.completion.WodParserCache;
import org.objectstyle.wolips.wodclipse.core.document.IWOEditor;
import org.objectstyle.wolips.wodclipse.core.refactoring.RefactoringWodBinding;
import org.objectstyle.wolips.wodclipse.core.refactoring.RefactoringWodElement;
import org.objectstyle.wolips.wodclipse.core.util.ICursorPositionListener;
import org.objectstyle.wolips.wodclipse.core.util.WodModelUtils;
public class BindingsInspector extends Composite implements ISelectionProvider, ISelectionChangedListener, ICursorPositionListener {
private WodParserCache _cache;
private TextEditor _lastEditor;
private Point _lastPosition;
private Combo _elementTypeField;
private Text _elementNameField;
private TableViewer _bindingsTableViewer;
private Button _addBindingButton;
private Button _removeBindingButton;
private Button _addKeyActionButton;
private BindingsLabelProvider _nameLabelProvider;
private BindingsLabelProvider _valueLabelProvider;
private BindingsContentProvider _bindingsContentProvider;
private DataBindingContext _dataBindingContext;
private IWodElement _wodElement;
private RefactoringWodElement _refactoringElement;
private List<WodProblem> _wodProblems;
private List<ISelectionChangedListener> _listeners = new LinkedList<ISelectionChangedListener>();
public BindingsInspector(Composite parent, int style) {
super(parent, style);
setLayout(new GridLayout(2, false));
Label elementNameLabel = new Label(this, SWT.NONE);
elementNameLabel.setText("Component Name");
_elementNameField = new Text(this, SWT.BORDER);
_elementNameField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
Label elementTypeLabel = new Label(this, SWT.NONE);
elementTypeLabel.setText("Component Type");
_elementTypeField = new Combo(this, SWT.BORDER);
_elementTypeField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
_elementTypeField.setVisibleItemCount(5);
Composite bindingsTableContainer = new Composite(this, SWT.NONE);
GridData bindingsTableContainerData = new GridData(GridData.FILL_BOTH);
bindingsTableContainerData.horizontalSpan = 2;
bindingsTableContainer.setLayoutData(bindingsTableContainerData);
_bindingsTableViewer = new TableViewer(bindingsTableContainer, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION);
_bindingsContentProvider = new BindingsContentProvider();
_bindingsTableViewer.setContentProvider(_bindingsContentProvider);
// _bindingsTableViewer.setLabelProvider(_bindingsLabelProvider);
TableColumnLayout bindingsTableLayout = new TableColumnLayout();
bindingsTableContainer.setLayout(bindingsTableLayout);
Table bindingsTable = _bindingsTableViewer.getTable();
bindingsTable.setHeaderVisible(true);
bindingsTable.setLinesVisible(true);
ColumnViewerEditorActivationStrategy columnActivationStrategy = new ColumnViewerEditorActivationStrategy(_bindingsTableViewer) {
protected boolean isEditorActivationEvent(ColumnViewerEditorActivationEvent event) {
return event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL || event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION || event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC;
}
};
TableViewerEditor.create(_bindingsTableViewer, columnActivationStrategy, ColumnViewerEditor.TABBING_HORIZONTAL | ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR | ColumnViewerEditor.TABBING_VERTICAL | ColumnViewerEditor.KEYBOARD_ACTIVATION);
TableViewerColumn nameViewerColumn = new TableViewerColumn(_bindingsTableViewer, SWT.LEAD);
TableColumn nameColumn = nameViewerColumn.getColumn();
nameColumn.setText("Attribute");
bindingsTableLayout.setColumnData(nameColumn, new ColumnWeightData(50, true));
nameViewerColumn.setEditingSupport(new BindingNameEditingSupport(_bindingsTableViewer));
_nameLabelProvider = new BindingsLabelProvider(0);
nameViewerColumn.setLabelProvider(_nameLabelProvider);
TableViewerColumn valueViewerColumn = new TableViewerColumn(_bindingsTableViewer, SWT.LEAD);
TableColumn valueColumn = valueViewerColumn.getColumn();
valueColumn.setText("Binding");
bindingsTableLayout.setColumnData(valueColumn, new ColumnWeightData(50, true));
valueViewerColumn.setEditingSupport(new BindingValueEditingSupport(_bindingsTableViewer));
_valueLabelProvider = new BindingsLabelProvider(1);
valueViewerColumn.setLabelProvider(_valueLabelProvider);
_bindingsTableViewer.addSelectionChangedListener(this);
Composite buttonContainer = new Composite(this, SWT.NONE);
GridData buttonContainerData = new GridData(GridData.FILL_HORIZONTAL);
buttonContainerData.horizontalSpan = 2;
buttonContainer.setLayoutData(buttonContainerData);
RowLayout buttonLayout = new RowLayout(SWT.HORIZONTAL);
buttonLayout.marginHeight = 0;
buttonLayout.marginWidth = 0;
buttonLayout.marginTop = 0;
buttonLayout.marginLeft = 0;
buttonLayout.marginBottom = 0;
buttonLayout.marginRight = 0;
buttonLayout.justify = true;
buttonLayout.fill = true;
buttonLayout.pack = true;
buttonContainer.setLayout(buttonLayout);
_addBindingButton = new Button(buttonContainer, SWT.PUSH);
_addBindingButton.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
public void widgetSelected(SelectionEvent e) {
BindingsInspector.this.addNewBinding();
}
});
_addBindingButton.setText("New Binding");
_removeBindingButton = new Button(buttonContainer, SWT.PUSH);
_removeBindingButton.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
public void widgetSelected(SelectionEvent e) {
BindingsInspector.this.removeBinding();
}
});
_removeBindingButton.setText("Remove Binding");
_addKeyActionButton = new Button(buttonContainer, SWT.PUSH);
_addKeyActionButton.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
public void widgetSelected(SelectionEvent e) {
BindingsInspector.this.addKey();
}
});
_addKeyActionButton.setText("Add Key");
setWodElement(null, null);
}
public void setWodElement(IWodElement wodElement, WodParserCache cache) {
if (_elementNameField.isDisposed() || _elementTypeField.isDisposed() || _bindingsTableViewer.getTable().isDisposed()) {
return;
}
if (_dataBindingContext != null) {
_dataBindingContext.dispose();
}
_cache = cache;
_wodElement = wodElement;
_wodProblems = null;
if (wodElement != null && cache != null) {
try {
_wodProblems = WodModelUtils.getProblems(wodElement, cache);
} catch (Throwable t) {
t.printStackTrace();
}
}
_nameLabelProvider.setContext(_wodElement, _wodProblems);
_valueLabelProvider.setContext(_wodElement, _wodProblems);
if (cache != null) {
try {
_bindingsContentProvider.setContext(cache.getJavaProject(), WodParserCache.getTypeCache());
} catch (Exception e) {
e.printStackTrace();
}
} else {
_bindingsContentProvider.setContext(null, null);
}
if (_bindingsTableViewer != null && !_bindingsTableViewer.getControl().isDisposed()) {
_bindingsTableViewer.setInput(_wodElement);
} else {
_bindingsTableViewer.setInput(new Object[0]);
}
IApiBinding selectedBinding = (IApiBinding) ((IStructuredSelection) _bindingsTableViewer.getSelection()).getFirstElement();
if (_wodElement != null && selectedBinding != null) {
String selectedBindingName = selectedBinding.getName();
Wo api = _bindingsContentProvider.getApi();
if (api != null) {
IApiBinding newBinding = api.getBinding(selectedBindingName);
if (newBinding != null) {
_bindingsTableViewer.setSelection(new StructuredSelection(newBinding));
}
}
}
String elementName = "none";
boolean elementNameEnabled = false;
String elementType = "";
boolean elementTypeEnabled = false;
if (_wodElement != null) {
if (_wodElement.isInline()) {
elementName = "inline";
} else {
elementName = _wodElement.getElementName();
elementNameEnabled = true;
}
elementType = _wodElement.getElementType();
if (elementType == null) {
elementType = "<unknown>";
}
elementTypeEnabled = true;
}
_elementNameField.setText(elementName);
_elementNameField.setEnabled(elementNameEnabled);
_elementTypeField.setText(elementType);
_elementTypeField.setEnabled(elementTypeEnabled);
if (cache != null) {
_dataBindingContext = new DataBindingContext();
_refactoringElement = new RefactoringWodElement(_wodElement, cache);
if (elementNameEnabled) {
bindElementName(cache);
}
if (elementTypeEnabled) {
bindElementType();
}
}
enableButtons();
}
protected void addNewBinding() {
RefactoringWodElement element = getRefactoringElement();
if (element != null) {
try {
String newBindingName = RefactoringWodElement.findUnusedBindingName(element.getWodElement(), "newBinding");
element.addBindingValueNamed("\"\"", null, newBindingName);
BindingsInspector.this.refresh();
} catch (Exception e) {
e.printStackTrace();
}
}
}
protected void removeBinding() {
IApiBinding binding = (IApiBinding) ((IStructuredSelection) _bindingsTableViewer.getSelection()).getFirstElement();
if (binding != null) {
RefactoringWodElement element = getRefactoringElement();
if (element != null) {
try {
element.removeBindingNamed(binding.getName());
BindingsInspector.this.refresh();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
protected void addKey() {
IApiBinding binding = (IApiBinding) ((IStructuredSelection) _bindingsTableViewer.getSelection()).getFirstElement();
if (binding != null && _cache != null) {
try {
BindingValueKeyPath bindingValueKeyPath = new BindingValueKeyPath(_wodElement.getBindingValue(binding.getName()), _cache);
if (bindingValueKeyPath.canAddKey()) {
String name = WodCompletionUtils.addKeyOrAction(bindingValueKeyPath, binding, _cache.getComponentType());
getRefactoringElement().setValueForBinding(name, binding.getName());
BindingsInspector.this.refresh();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
protected void enableButtons() {
if (_wodElement == null) {
_addBindingButton.setEnabled(false);
_removeBindingButton.setEnabled(false);
_addKeyActionButton.setEnabled(false);
} else {
_addBindingButton.setEnabled(true);
IApiBinding binding = (IApiBinding) ((IStructuredSelection) _bindingsTableViewer.getSelection()).getFirstElement();
if (binding == null || _cache == null) {
_removeBindingButton.setEnabled(false);
_addKeyActionButton.setEnabled(false);
} else {
_removeBindingButton.setEnabled(true);
try {
BindingValueKeyPath bindingValueKeyPath = new BindingValueKeyPath(_wodElement.getBindingValue(binding.getName()), _cache);
if (bindingValueKeyPath.canAddKey()) {
_addKeyActionButton.setEnabled(true);
} else {
_addKeyActionButton.setEnabled(false);
}
} catch (Exception e) {
e.printStackTrace();
_addKeyActionButton.setEnabled(false);
}
}
}
}
protected void bindElementType() {
UpdateValueStrategy elementTypeUpdateStrategy = new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE);
elementTypeUpdateStrategy.setBeforeSetValidator(new IValidator() {
public IStatus validate(Object value) {
String newName = (String) value;
System.out.println(".validate: " + newName);
IStatus status = Status.OK_STATUS;
try {
if (newName == null || newName.length() == 0) {
status = ValidationStatus.error("Element types cannot be blank.");
} else if (newName.contains(" ")) {
status = ValidationStatus.error("Element types do not allow spaces.");
}
} catch (Exception e) {
status = ValidationStatus.error("Failed to change element type.", e);
}
// reset the value back on failure
if (!status.isOK()) {
getElementTypeField().setText(getRefactoringElement().getElementType());
}
return status;
}
});
// _dataBindingContext.bindValue(SWTObservables.observeText(_elementTypeField),
// BeansObservables.observeValue(_refactoringElement,
// RefactoringElementModel.ELEMENT_TYPE),
// elementTypeUpdateStrategy, null);
_elementTypeField.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
// DO NOTHING
}
public void focusLost(FocusEvent e) {
try {
String elementTypeFieldText = getElementTypeField().getText();
String elementTypeModelText = getRefactoringElement().getElementType();
if (!ComparisonUtils.equals(elementTypeModelText, elementTypeFieldText, true)) {
getRefactoringElement().setElementType(elementTypeFieldText);
BindingsInspector.this.refresh();
}
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
protected void bindElementName(final WodParserCache refactoringParserCache) {
UpdateValueStrategy elementNameUpdateStrategy = new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE);
elementNameUpdateStrategy.setBeforeSetValidator(new IValidator() {
public IStatus validate(Object value) {
String newName = (String) value;
IStatus status = Status.OK_STATUS;
try {
if (newName == null || newName.length() == 0) {
status = ValidationStatus.error("Element names cannot be blank.");
} else if (newName.contains(" ")) {
status = ValidationStatus.error("Element names do not allow spaces.");
} else if (refactoringParserCache.getWodEntry().getModel().getElementNamed(newName) != null) {
status = ValidationStatus.error("There is already an element named '" + newName + "'.");
}
} catch (Exception e) {
status = ValidationStatus.error("Failed to change element name.", e);
}
// reset the value back on failure
if (!status.isOK()) {
getElementNameField().setText(getRefactoringElement().getElementName());
}
return status;
}
});
_dataBindingContext.bindValue(SWTObservables.observeText(_elementNameField, SWT.FocusOut), BeansObservables.observeValue(_refactoringElement, RefactoringWodElement.ELEMENT_NAME), elementNameUpdateStrategy, null);
}
public TableViewer getBindingsTableViewer() {
return _bindingsTableViewer;
}
public void selectionChanged(SelectionChangedEvent event) {
enableButtons();
SelectionChangedEvent wrappedEvent = new SelectionChangedEvent(this, getSelection());
for (Iterator listeners = _listeners.iterator(); listeners.hasNext();) {
ISelectionChangedListener listener = (ISelectionChangedListener) listeners.next();
listener.selectionChanged(wrappedEvent);
}
}
public void addSelectionChangedListener(ISelectionChangedListener listener) {
_listeners.add(listener);
}
public void setSelection(ISelection selection) {
_bindingsTableViewer.setSelection(selection);
}
public ISelection getSelection() {
return _bindingsTableViewer.getSelection();
}
public void removeSelectionChangedListener(ISelectionChangedListener listener) {
_listeners.remove(listener);
}
public RefactoringWodElement getRefactoringElement() {
return _refactoringElement;
}
public Text getElementNameField() {
return _elementNameField;
}
public Combo getElementTypeField() {
return _elementTypeField;
}
public IWodElement getWodElement() {
return _wodElement;
}
public List<WodProblem> getWodProblems() {
return _wodProblems;
}
public TextEditor getLastEditor() {
return _lastEditor;
}
@Override
public void dispose() {
if (_dataBindingContext != null) {
_dataBindingContext.dispose();
_dataBindingContext = null;
}
super.dispose();
}
public void refresh() {
if (_bindingsTableViewer == null) {
return;
}
if (_lastEditor != null && _lastPosition != null) {
cursorPositionChanged(_lastEditor, _lastPosition);
}
}
public void cursorPositionChanged(TextEditor editor, Point selectionRange) {
_lastEditor = editor;
_lastPosition = selectionRange;
WodParserCache cache = null;
IWodElement wodElement = null;
if (editor instanceof IWOEditor) {
try {
IWOEditor woEditor = (IWOEditor) editor;
cache = woEditor.getParserCache();
wodElement = woEditor.getSelectedElement(true, true);
} catch (Throwable t) {
t.printStackTrace();
}
}
setWodElement(wodElement, cache);
}
public class BindingNameEditingSupport extends EditingSupport {
private TextCellEditor _nameEditor;
public BindingNameEditingSupport(TableViewer viewer) {
super(viewer);
_nameEditor = new WOTextCellEditor(viewer.getTable());
}
@Override
protected boolean canEdit(Object element) {
return true;
}
@Override
protected CellEditor getCellEditor(Object element) {
return _nameEditor;
}
@Override
protected Object getValue(Object element) {
String value = null;
IApiBinding binding = (IApiBinding) element;
if (binding != null) {
value = binding.getName();
}
if (value == null) {
value = "<none>";
}
return value;
}
@Override
protected void setValue(Object element, Object value) {
IApiBinding binding = (IApiBinding) element;
if (binding != null) {
IWodElement wodElement = getWodElement();
if (wodElement != null) {
try {
RefactoringWodBinding wodBinding = getRefactoringElement().getBindingNamed(binding.getName());
if (wodBinding != null) {
wodBinding.setName((String) value);
}
} catch (Exception e) {
e.printStackTrace();
}
BindingsInspector.this.refresh();
}
}
}
}
public class BindingValueEditingSupport extends EditingSupport {
private TextCellEditor _valueEditor;
public BindingValueEditingSupport(TableViewer viewer) {
super(viewer);
_valueEditor = new WOTextCellEditor(viewer.getTable());
}
@Override
protected boolean canEdit(Object element) {
return true;
}
@Override
protected CellEditor getCellEditor(Object element) {
return _valueEditor;
}
@Override
protected Object getValue(Object element) {
String value = null;
IApiBinding binding = (IApiBinding) element;
if (binding != null) {
IWodElement wodElement = getWodElement();
if (wodElement != null) {
IWodBinding wodBinding = wodElement.getBindingNamed(binding.getName());
if (wodBinding != null) {
value = wodBinding.getValue();
}
}
}
if (value == null) {
value = "";
}
return value;
}
@Override
protected void setValue(Object element, Object value) {
IApiBinding binding = (IApiBinding) element;
if (binding != null) {
IWodElement wodElement = getWodElement();
if (wodElement != null) {
try {
getRefactoringElement().setValueForBinding((String) value, binding.getName());
BindingsInspector.this.refresh();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
}