/*******************************************************************************
* Copyright (c) 2006-2013, Cloudsmith Inc.
* The code, documentation and other materials contained herein have been
* licensed under the Eclipse Public License - v 1.0 by the copyright holder
* listed above, as the Initial Contributor under such license. The text of
* such license is available at www.eclipse.org.
******************************************************************************/
package org.eclipse.buckminster.ui.general.editor.structured;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.buckminster.ui.general.editor.ITableModifyListener;
import org.eclipse.buckminster.ui.general.editor.Table;
import org.eclipse.buckminster.ui.general.editor.TableModifyEvent;
import org.eclipse.buckminster.ui.general.editor.TableModifyEventType;
import org.eclipse.buckminster.ui.general.editor.ValidatorException;
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.Composite;
import org.eclipse.swt.widgets.Control;
/**
* @author Karel Brezina
*
*/
public abstract class StructuredTable<T> extends Table<T> implements IStructuredTable<T> {
class CompoundFieldModifyListener<E> implements ModifyListener, SelectionListener, ITableModifyListener<E> {
@Override
public void modifyTable(TableModifyEvent<E> e) {
notifyFieldListeners(e);
}
@Override
public void modifyText(ModifyEvent e) {
if (!suppressFieldListener)
notifyFieldListeners(e);
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
// nothing
}
@Override
public void widgetSelected(SelectionEvent e) {
if (!suppressFieldListener)
notifyFieldListeners(e);
}
}
@SuppressWarnings("rawtypes")
protected final CompoundFieldModifyListener FIELD_LISTENER = new CompoundFieldModifyListener();
private List<String> stackKeys = new ArrayList<String>();
private Map<String, Control> stackMap = new HashMap<String, Control>();
private List<IFieldModifyListener> fieldListeners = new ArrayList<IFieldModifyListener>();
private boolean suppressFieldListener = false;
/**
* Creates Table instance
*
* @param data
* input data that will be edited
*/
public StructuredTable(List<T> data, boolean readOnly) {
super(data, readOnly);
// notify field listeners about row removal
addTableModifyListener(new ITableModifyListener<T>() {
@Override
public void modifyTable(TableModifyEvent<T> e) {
if (e.getEventType() == TableModifyEventType.REMOVE_ROW)
notifyFieldListeners(e);
}
});
}
@Override
public T addEmptyRow() {
T tableRow = createNewRow();
getRows().add(tableRow);
return tableRow;
}
public void addFieldModifyListener(IFieldModifyListener listener) {
if (!fieldListeners.contains(listener)) {
fieldListeners.add(listener);
}
}
@Override
public void fillStackComposite(Composite stackComposite) {
clearStackMapping();
fillStack(stackComposite);
}
@Override
public Control getStackControl(String stackKey) {
return stackMap.get(stackKey);
}
@Override
public List<String> getStackKeys() {
return stackKeys;
}
@Override
public int getTableViewerColumns() {
return getTableViewerColumnHeaders().length;
}
@Override
public void refreshRow(int rowIdx) {
T builder;
if (rowIdx == -1) {
builder = createNewRow();
} else {
builder = getRow(rowIdx);
}
suppressFieldListener = true;
refreshRow(builder);
suppressFieldListener = false;
}
public void removeFieldModifyListener(IFieldModifyListener listener) {
fieldListeners.remove(listener);
}
@Override
public void save(int rowIdx) throws ValidatorException {
if (rowIdx == -1) {
T tableRow = createNewRow();
getRows().add(tableRow);
try {
setRowValues(tableRow);
} catch (ValidatorException e) {
getRows().remove(tableRow);
throw e;
}
notifyListeners(TableModifyEventType.ADD_ROW, getRows().size() - 1, tableRow);
} else {
T tableRow = getRows().get(rowIdx);
setRowValues(tableRow);
notifyListeners(TableModifyEventType.UPDATE_ROW, rowIdx, tableRow);
}
}
@Override
public boolean swapRows(int rowIdx, int idxOffset) {
int idx = rowIdx + idxOffset;
if (idx <= 0)
return false;
List<T> data = getRows();
if (idx >= data.size()) {
return false;
}
data.set(idx - 1, data.set(idx, data.get(idx - 1)));
int newIdx = rowIdx + idxOffset;
if (idxOffset == 0) {
newIdx = rowIdx - 1;
}
notifyListeners(TableModifyEventType.SWAP_ROW, newIdx, data.get(newIdx));
notifyListeners(TableModifyEventType.SWAP_ROW, rowIdx, data.get(rowIdx));
return true;
}
protected void addStackMapping(String key, Control control) {
stackKeys.add(key);
stackMap.put(key, control);
}
/**
* Creates new row
*
* @return new row
*/
protected abstract T createNewRow();
/**
* Fills controls to the stack composite
*
* @param stackComposite
*/
protected abstract void fillStack(Composite stackComposite);
protected void notifyFieldListeners(Object originalEvent) {
FieldModifyEvent e = new FieldModifyEvent(originalEvent);
for (IFieldModifyListener listener : fieldListeners)
listener.modifyField(e);
}
/**
* Refreshes controls from a given data row
*
* @param builder
*/
protected abstract void refreshRow(T builder);
/**
* Sets values from controls to row
*
* @param row
* data row
* @throws ValidatorException
*/
protected abstract void setRowValues(T row) throws ValidatorException;
private void clearStackMapping() {
stackKeys.clear();
stackMap.clear();
}
}