package org.objectstyle.wolips.componenteditor.inspector;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
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.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.objectstyle.wolips.baseforplugins.util.ComparisonUtils;
import org.objectstyle.wolips.bindings.wod.BindingValueKey;
import org.objectstyle.wolips.bindings.wod.BindingValueKeyPath;
import org.objectstyle.wolips.wodclipse.core.completion.WodParserCache;
public class WOBrowser extends ScrolledComposite implements ISelectionChangedListener, ISelectionProvider, KeyListener {
private Composite _browserComposite;
private List<WOBrowserColumn> _columns;
private List<ISelectionChangedListener> _listeners = new LinkedList<ISelectionChangedListener>();
private IWOBrowserDelegate _browserDelegate;
private StringBuffer _keypathBuffer;
private long _lastKeyTime;
public WOBrowser(Composite parent, int style) {
super(parent, SWT.H_SCROLL | style);
_keypathBuffer = new StringBuffer();
_columns = new LinkedList<WOBrowserColumn>();
_browserComposite = new Composite(this, SWT.NONE);
_browserComposite.setBackground(parent.getBackground());
// _browser.setLayoutData(new GridData(GridData.FILL_BOTH));
setContent(_browserComposite);
setExpandVertical(true);
GridLayout browserLayout = new GridLayout(1, false);
browserLayout.horizontalSpacing = 0;
browserLayout.marginWidth = 5;
browserLayout.marginHeight = 5;
browserLayout.horizontalSpacing = 5;
_browserComposite.setLayout(browserLayout);
}
public void setBrowserDelegate(IWOBrowserDelegate browserDelegate) {
_browserDelegate = browserDelegate;
for (WOBrowserColumn column : _columns) {
column.setDelegate(browserDelegate);
}
}
public IWOBrowserDelegate getBrowserDelegate() {
return _browserDelegate;
}
public WOBrowserColumn setRootType(IType type) throws JavaModelException {
disposeToColumn(-1);
return addType(type);
}
public WOBrowserColumn addType(IType type) throws JavaModelException {
WOBrowserColumn newColumn = null;
if (type != null) {
newColumn = new WOBrowserColumn(this, type, _browserComposite, SWT.NONE);
newColumn.getViewer().getTable().addKeyListener(this);
newColumn.setDelegate(_browserDelegate);
newColumn.addSelectionChangedListener(this);
GridData columnLayoutData = new GridData(GridData.FILL_BOTH);
newColumn.setLayoutData(columnLayoutData);
_columns.add(newColumn);
if (_browserDelegate != null) {
_browserDelegate.browserColumnAdded(newColumn);
}
((GridLayout) _browserComposite.getLayout()).numColumns = _columns.size();
_browserComposite.pack();
for (WOBrowserColumn column : _columns) {
Object selectedElement = ((IStructuredSelection) column.getSelection()).getFirstElement();
if (selectedElement != null) {
column.getViewer().reveal(selectedElement);
}
}
getHorizontalBar().setSelection(getHorizontalBar().getMaximum());
layout();
}
return newColumn;
}
public void disposeToColumn(WOBrowserColumn column) {
int columnIndex = _columns.indexOf(column);
if (columnIndex != -1) {
disposeToColumn(columnIndex);
}
}
public void disposeToColumn(int columnIndex) {
for (int columnNum = _columns.size() - 1; columnNum > columnIndex; columnNum--) {
WOBrowserColumn column = _columns.get(columnNum);
if (_browserDelegate != null) {
_browserDelegate.browserColumnRemoved(column);
}
column.dispose();
_columns.remove(columnNum);
}
_browserComposite.pack();
}
public WOBrowserColumn selectKeyInColumn(BindingValueKey selectedKey, WOBrowserColumn column) {
WOBrowserColumn addedColumn = null;
disposeToColumn(column);
if (selectedKey == null) {
// System.out.println("WOBrowserPage.selectionChanged: none");
} else {
try {
if (!selectedKey.isLeaf()) {
IType nextType = selectedKey.getNextType();
if (nextType != null) {
addedColumn = addType(nextType);
}
}
} catch (JavaModelException e) {
e.printStackTrace();
}
}
return addedColumn;
}
public void selectionChanged(SelectionChangedEvent event) {
WOBrowserColumn selectedColumn = (WOBrowserColumn) event.getSource();
IStructuredSelection selection = (IStructuredSelection) event.getSelection();
Object selectedObject = selection.getFirstElement();
if (selectedObject instanceof BindingValueKey) {
BindingValueKey selectedKey = (BindingValueKey) selectedObject;
selectKeyInColumn(selectedKey, selectedColumn);
}
else {
selectKeyInColumn(null, selectedColumn);
}
SelectionChangedEvent wrappedEvent = new SelectionChangedEvent(this, getSelection());
for (Iterator listeners = _listeners.iterator(); listeners.hasNext();) {
ISelectionChangedListener listener = (ISelectionChangedListener) listeners.next();
listener.selectionChanged(wrappedEvent);
}
}
public WOBrowserColumn getFocusedColumn() {
WOBrowserColumn focusedColumn = null;
for (WOBrowserColumn column : _columns) {
if (column.getViewer().getTable().isFocusControl()) {
focusedColumn = column;
}
}
return focusedColumn;
}
public WOBrowserColumn getSelectedColumn() {
WOBrowserColumn selectedColumn = null;
for (WOBrowserColumn column : _columns) {
if (column.getSelectedKey() != null) {
selectedColumn = column;
}
}
return selectedColumn;
}
public String getSelectedKeyPath() {
return getSelectedKeyPath(null);
}
public String getSelectedKeyPath(WOBrowserColumn throughColumn) {
StringBuffer keyPath = new StringBuffer();
for (WOBrowserColumn column : _columns) {
BindingValueKey key = column.getSelectedKey();
if (key != null) {
if (keyPath.length() > 0) {
keyPath.append('.');
}
keyPath.append(key.getBindingName());
if (throughColumn == column) {
break;
}
}
}
return keyPath.toString();
}
public void addSelectionChangedListener(ISelectionChangedListener listener) {
_listeners.add(listener);
}
public ISelection getSelection() {
return new StructuredSelection(getSelectedKeyPath());
}
public void removeSelectionChangedListener(ISelectionChangedListener listener) {
_listeners.remove(listener);
}
public void setSelection(ISelection selection) {
Object selectedObject = ((IStructuredSelection) selection).getFirstElement();
if (selectedObject == null || selectedObject instanceof String) {
String selectedKeyPath = (String) selectedObject;
if (selectedKeyPath == null) {
WOBrowserColumn column = _columns.get(0);
selectKeyInColumn(null, column);
column.setSelection(new StructuredSelection());
} else {
try {
if (!ComparisonUtils.equals(selectedKeyPath, getSelectedKeyPath())) {
BindingValueKeyPath bindingValueKeyPath = new BindingValueKeyPath(selectedKeyPath, _columns.get(0).getType(), WodParserCache.getTypeCache());
disposeToColumn(0);
if (bindingValueKeyPath != null && bindingValueKeyPath.isValid()) {
BindingValueKey[] bindingKeys = bindingValueKeyPath.getBindingKeys();
if (bindingKeys != null) {
for (BindingValueKey bindingValueKey : bindingKeys) {
WOBrowserColumn column = _columns.get(_columns.size() - 1);
column.setSelection(new StructuredSelection(bindingValueKey));
WOBrowserColumn newColumn = selectKeyInColumn(bindingValueKey, column);
if (newColumn == null) {
break;
}
}
}
}
}
} catch (JavaModelException e) {
e.printStackTrace();
}
}
}
}
protected String getPreviousSelectedKeyPath() {
String previousSelectedKeyPath = null;
String selectedKey = getSelectedKeyPath();
if (selectedKey.length() > 0) {
int dotIndex = selectedKey.lastIndexOf('.');
if (dotIndex != -1) {
previousSelectedKeyPath = selectedKey.substring(0, dotIndex);
}
}
return previousSelectedKeyPath;
}
public void selectPreviousColumn() {
String previousSelectedKeyPath = getPreviousSelectedKeyPath();
if (previousSelectedKeyPath != null) {
setSelection(new StructuredSelection(previousSelectedKeyPath));
WOBrowserColumn previousColumn = getSelectedColumn();
if (previousColumn != null) {
previousColumn.setFocus();
}
}
clearKeyBuffer();
}
public void selectNextColumn() {
WOBrowserColumn column = getSelectedColumn();
if (column != null) {
int columnIndex = _columns.indexOf(column);
if (columnIndex < _columns.size() - 1) {
WOBrowserColumn nextColumn = _columns.get(_columns.size() - 1);
Object firstElement = nextColumn.getViewer().getElementAt(0);
nextColumn.setSelection(new StructuredSelection(firstElement));
nextColumn.setFocus();
}
}
clearKeyBuffer();
}
protected void clearKeyBuffer() {
_keypathBuffer.setLength(0);
}
protected void selectFromKeyBuffer() {
if (_keypathBuffer.length() > 0) {
WOBrowserColumn focusedColumn = getFocusedColumn();
if (focusedColumn != null) {
BindingValueKey matchingKey = focusedColumn.getBindingValueKeyStartingWith(_keypathBuffer.toString());
disposeToColumn(focusedColumn);
if (matchingKey != null) {
focusedColumn.setSelection(new StructuredSelection(matchingKey));
}
}
}
}
protected void deleteFromKeyBuffer() {
if (_keypathBuffer.length() > 0) {
_keypathBuffer.setLength(_keypathBuffer.length() - 1);
}
selectFromKeyBuffer();
_lastKeyTime = System.currentTimeMillis();
}
protected void appendToKeyBuffer(char ch) {
long keyTime = System.currentTimeMillis();
if ((keyTime - _lastKeyTime) > 1000 || _keypathBuffer.length() == 0) {
_keypathBuffer.setLength(0);
}
_keypathBuffer.append(ch);
selectFromKeyBuffer();
_lastKeyTime = keyTime;
}
public void keyPressed(KeyEvent e) {
if (e.keyCode == SWT.ARROW_LEFT) {
selectPreviousColumn();
} else if (e.keyCode == SWT.ARROW_RIGHT) {
selectNextColumn();
} else if (e.keyCode == SWT.ESC) {
clearKeyBuffer();
} else if (e.character == '.') {
selectNextColumn();
} else if (e.keyCode == SWT.BS || e.keyCode == SWT.DEL) {
deleteFromKeyBuffer();
} else if (e.character != 0) {
appendToKeyBuffer(e.character);
}
}
public void keyReleased(KeyEvent e) {
// TODO
}
}