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(); } } } } } }