package com.onpositive.commons.ui.tableeditor;
import java.io.EOFException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.viewers.IOpenListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.TableColumn;
public abstract class ConfigurableTableViewer {
private String currentSort;
public void dispose() {
try {
storeVisibleColumns();
storeColumnsWidth();
} catch (CoreException e) {
e.printStackTrace();
}
}
private final class FieldUpdateRunnable implements Runnable {
private final Field[] fields;
private FieldUpdateRunnable(Field[] fields) {
this.fields = fields;
}
public void run() {
int so = 0;
try {
if (currentFields != null && currentFields.length != 0) {
storeColumnsWidth();
storeVisibleColumns();
storeColumnsSort(currentSort != null ? currentSort : "");
storeColumnsSortAscending(viewer.getTable()
.getSortDirection());
}
currentSort = getColumnsSort();
so = getColumnsSortAscending();
} catch (CoreException e1) {
e1.printStackTrace();
}
currentFields = fields;
filters.getParent().setRedraw(false);
filters.getParent().setLayoutDeferred(true);
HashMap<String, Integer> cmap = new HashMap<String, Integer>();
parseCmap(cmap);
try {
restoreVisibleColumns();
} catch (CoreException e) {
e.printStackTrace();
}
viewer.getTable().setRedraw(false);
filters.setRedraw(false);
try {
map.clear();
if (viewer != null && !viewer.getTable().isDisposed()) {
for (TableColumn c : viewer.getTable().getColumns()) {
c.dispose();
}
for (Control c : filters.getChildren()) {
c.dispose();
}
viewer.getTable().removeAll();
for (final Field f : fields) {
final TableColumn tableColumn = new TableColumn(viewer
.getTable(), SWT.LEFT);
tableColumn.setData("field", f);
if (f.name.equals(currentSort)) {
viewer.getTable().setSortColumn(tableColumn);
viewer.getTable().setSortDirection(so);
}
tableColumn.setText(f.getTitle());
tableColumn.addSelectionListener(new SortListener(
tableColumn, f));
if (f.needsFilter()) {
Control createFilterControl = f
.createFilterControl(filters);
map.put(tableColumn, createFilterControl);
}
Integer integer = cmap.get(f.name);
if (integer == null) {
integer = 100;
}
if (!currentColumns.isEmpty()){ //!currentColumns.isEmpty()
if (currentColumns.contains(f.name)){//!currentColumns.contains(f.name)
integer=0;
}
}
tableColumn.setWidth(integer.intValue());
Listener listener = new Listener() {
public void handleEvent(Event event) {
updateFilters();
}
};
tableColumn.addListener(SWT.Resize, listener);
}
GridData gridData = new GridData(-1, 25);
gridData.horizontalAlignment = GridData.FILL;
gridData.verticalAlignment = GridData.BEGINNING;
gridData.grabExcessHorizontalSpace = true;
filters.setLayoutData(gridData);
filters.getParent().setLayoutDeferred(false);
filters.getParent().layout(true);
filters.getParent().setRedraw(true);
holder.setLayoutDeferred(false);
holder.layout(true, true);
updateFilters();
holder.setRedraw(true);
}
} finally {
viewer.getTable().setRedraw(true);
filters.setRedraw(true);
}
}
private void parseCmap(HashMap<String, Integer> cmap) {
try {
String columnWidthString = getColumnWidthString();
if (columnWidthString != null) {
String[] split = columnWidthString.split(";");
for (String s : split) {
int indexOf = s.indexOf('=');
if (indexOf != -1) {
cmap.put(s.substring(0, indexOf), Integer
.parseInt(s.substring(indexOf + 1)));
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private final class SortListener implements SelectionListener {
private final TableColumn tableColumn;
private final Field f;
private SortListener(TableColumn tableColumn, Field f) {
this.tableColumn = tableColumn;
this.f = f;
}
public void widgetSelected(SelectionEvent e) {
if (!allowSort(f)) {
return;
}
currentSort = f.name;
if (viewer.getTable().getSortColumn() != tableColumn) {
viewer.getTable().setSortColumn(tableColumn);
if (allowOrder(f, SWT.UP)) {
viewer.getTable().setSortDirection(SWT.UP);
query.sort.property = f.name;
query.sort.ascending = true;
}
} else {
int sortDirection = viewer.getTable().getSortDirection();
if (sortDirection == SWT.UP) {
if (allowOrder(f, SWT.DOWN)) {
sortDirection = SWT.DOWN;
viewer.getTable().setSortDirection(sortDirection);
query.sort.property = f.name;
query.sort.ascending = false;
}
} else {
if (allowOrder(f, SWT.UP)) {
sortDirection = SWT.UP;
viewer.getTable().setSortDirection(sortDirection);
query.sort.property = f.name;
query.sort.ascending = true;
}
}
}
refreshSort(facade);
}
public void widgetDefaultSelected(SelectionEvent e) {
}
}
private final class UpdateRunnable implements Runnable {
private final Object[] object;
private UpdateRunnable(Object[] object) {
this.object = object;
}
public void run() {
if (currentFields == null) {
currentFields = new Field[0];
}
if (viewer != null && !viewer.getTable().isDisposed()) {
viewer.getTable().setRedraw(false);
if (true) {
viewer.add(object);
}
viewer.getTable().setRedraw(true);
}
updateFilters();
ConfigurableTableViewer.this
.selectionChanged((IStructuredSelection) viewer
.getSelection());
}
private void updateFilters() {
for (TableColumn m : map.keySet()) {
Control combo = map.get(m);
combo.setRedraw(false);
try {
for (Field f : currentFields) {
if (f.equals(m.getData("field"))) {
f.updateFilterControl(f.name, combo,
new IFilterListener() {
public void filterValueChangedTo(
String filter, Object newValue) {
query.setFilter(filter, newValue);
}
public void clearFilter(String name) {
query.removeFilter(name);
}
});
}
}
} finally {
combo.setRedraw(true);
}
}
}
}
private final class ConfigurableTableProvider extends LabelProvider
implements ITableLabelProvider {
public Image getColumnImage(Object element, int columnIndex) {
return currentFields[columnIndex].getImage(element);
}
public String getColumnText(Object element, int columnIndex) {
return currentFields[columnIndex].getText(element);
}
}
public void refresh(Object object) {
viewer.refresh(object);
}
private Composite holder;
private Composite filters;
private TableViewer viewer;
protected TableViewer getViewer() {
return viewer;
}
Field[] currentFields;
public abstract void selectionChanged(IStructuredSelection selection);
public String getColumnsWidthString() {
StringBuilder bld = new StringBuilder();
if (currentFields == null) {
return "";
}
for (int a = 0; a < currentFields.length; a++) {
TableColumn column = viewer.getTable().getColumn(a);
int width = column.getWidth();
bld.append(currentFields[a].name);
bld.append('=');
bld.append(width);
if (a != currentFields.length - 1) {
bld.append(';');
}
}
return bld.toString();
}
HashMap<TableColumn, Control> map = new HashMap<TableColumn, Control>();
private IDataCallback callback = new IDataCallback() {
public void objectsFetched(final Object[] object) {
Display.getDefault().syncExec(new UpdateRunnable(object));
}
public void fieldsFetched(final Field[] fields) {
if (Arrays.equals(currentFields, fields)) {
return;
}
Display.getDefault().syncExec(new FieldUpdateRunnable(fields));
}
public void failed(final Exception exception) {
Display.getDefault().syncExec(new Runnable() {
public void run() {
if (viewer != null && !viewer.getTable().isDisposed()) {
if( exception instanceof EOFException){
MessageDialog.openError(Display.getCurrent()
.getActiveShell(), "Error:"
+ exception.getMessage(), "Please update server-side part of your project");
}else{
MessageDialog.openError(Display.getCurrent()
.getActiveShell(), "Error:"
+ exception.getMessage(), exception.toString());
}
}
holder.setLayoutDeferred(false);
holder.layout(true, true);
holder.setRedraw(true);
}
});
}
public void start() {
Display.getDefault().syncExec(new Runnable() {
public void run() {
viewer.setSorter(null);
viewer.getTable().removeAll();
}
});
}
public void failed(final String message) {
Display.getDefault().syncExec(new Runnable() {
public void run() {
if (viewer != null && !viewer.getTable().isDisposed()) {
MessageDialog.openError(Display.getCurrent()
.getActiveShell(), "Error", message);
}
holder.setLayoutDeferred(false);
holder.layout(true, true);
holder.setRedraw(true);
}
});
}
public void removeSort() {
}
public void lookChanged(Object[] object) {
if (Display.getCurrent() != null) {
viewer.refresh(true);
} else
Display.getDefault().asyncExec(new Runnable() {
public void run() {
viewer.refresh(true);
}
});
}
};
private Query query;
public Query getQuery() {
return query;
}
private IDataFacade facade;
protected HashSet<String> currentColumns = new HashSet<String>();
public IDataFacade getFacade() {
return facade;
}
public void onOpen(Object selection) {
}
public void createControl(Composite parent) {
holder = new Composite(parent, SWT.BORDER);
GridLayout layout = new GridLayout(1, false);
layout.marginHeight = 0;
layout.verticalSpacing = 2;
layout.marginWidth = 0;
holder.setLayout(layout);
}
public Control getControl() {
return holder;
}
public void fillPopupMenu(IMenuManager manager) {
}
public void setDataFacade(final IDataFacade facade) {
holder.setRedraw(false);
holder.setLayoutDeferred(true);
try {
if (viewer != null) {
try {
storeColumnsWidth();
storeVisibleColumns();
} catch (CoreException e) {
e.printStackTrace();
}
viewer.getTable().dispose();
filters.dispose();
}
selectionChanged(new StructuredSelection());
viewer = new TableViewer(holder, SWT.BORDER | SWT.FULL_SELECTION
| SWT.MULTI);
viewer.getTable().addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
dispose();
}
});
MenuManager manager = new MenuManager();
manager.setRemoveAllWhenShown(true);
manager.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
fillPopupMenu(manager);
}
});
Menu createContextMenu = manager.createContextMenu(viewer
.getTable());
viewer.getTable().setMenu(createContextMenu);
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
ConfigurableTableViewer.this
.selectionChanged((IStructuredSelection) event
.getSelection());
}
});
viewer.getTable().getHorizontalBar().addSelectionListener(
new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
updateFilters();
}
public void widgetSelected(SelectionEvent e) {
updateFilters();
}
});
viewer.addOpenListener(new IOpenListener() {
public void open(OpenEvent event) {
IStructuredSelection sel = (IStructuredSelection) event
.getSelection();
onOpen(sel.getFirstElement());
}
});
viewer.setLabelProvider(new ConfigurableTableProvider());
viewer.setContentProvider(new IStructuredContentProvider() {
public void inputChanged(Viewer viewer, Object oldInput,
Object newInput) {
}
public void dispose() {
}
public Object[] getElements(Object inputElement) {
return facade.getCurrentElements();
}
});
viewer.setInput(facade);
viewer.getTable().setHeaderVisible(true);
viewer.getTable().setLinesVisible(true);
viewer.getTable().setLayoutData(
GridDataFactory.fillDefaults().grab(true, true).create());
filters = new Composite(holder, SWT.NONE);
filters.setLayoutData(GridDataFactory.fillDefaults().grab(true,
false).create());
refresh(facade);
} finally {
}
}
public void refreshSort(IDataFacade facade) {
refresh(facade);
}
public void refresh(IDataFacade facade) {
this.facade = facade;
if (query == null) {
query = facade.getDefaultQuery();
try {
currentSort = getColumnsSort();
if (currentSort != null && currentSort.length() > 0) {
int columnsSortAscending = getColumnsSortAscending();
query.sort = new Sort(currentSort,
columnsSortAscending == SWT.UP);
}
} catch (CoreException e) {
e.printStackTrace();
}
}
facade.query(query, callback);
}
protected abstract void storeColumnsWidth() throws CoreException;
protected abstract void storeVisibleColumns() throws CoreException ;
protected abstract void restoreVisibleColumns() throws CoreException ;
public abstract String getColumnWidthString() throws CoreException;
protected abstract void storeColumnsSort(String name) throws CoreException;
protected abstract void storeColumnsSortAscending(int order)
throws CoreException;
public abstract String getColumnsSort() throws CoreException;
public abstract int getColumnsSortAscending() throws CoreException;
private void updateFilters() {
int x = -(viewer.getTable().getHorizontalBar() != null ? viewer
.getTable().getHorizontalBar().getSelection() : 0);
TableColumn[] columns = viewer.getTable().getColumns();
for (TableColumn t : columns) {
Control combo = map.get(t);
int width = t.getWidth();
if (combo != null) {
Point computeSize = combo.computeSize(width, -1);
combo.setLocation(x + 1, 0);
combo.setSize(width - 1, computeSize.y + 4);
if (combo instanceof Composite) {
Composite m = (Composite) combo;
m.layout(true);
}
filters.redraw();
filters.update();
}
x += width;
}
}
public void add(Object object) {
viewer.add(object);
}
public Field[] getFields() {
return currentFields;
}
public IDataCallback getRefreshCallback() {
return new IDataCallback() {
public void objectsFetched(Object[] object) {
callback.objectsFetched(object);
}
public void fieldsFetched(Field[] fields) {
callback.fieldsFetched(fields);
}
public void failed(Exception exception) {
callback.failed(exception);
}
public void start() {
Display.getDefault().syncExec(new Runnable() {
public void run() {
viewer.setSorter(null);
viewer.getTable().removeAll();
}
});
}
public void failed(String message) {
callback.failed(message);
}
public void removeSort() {
Display.getDefault().syncExec(new Runnable() {
public void run() {
viewer.getTable().setSortColumn(null);
currentSort = "";
}
});
}
public void lookChanged(Object[] object) {
callback.lookChanged(object);
}
};
}
protected abstract boolean allowSort(Field f);
protected abstract boolean allowOrder(Field f, int order);
protected void updateColumns() {
TableColumn[] columns = viewer.getTable().getColumns();
HashSet<String> m = new HashSet<String>(currentColumns);
for (TableColumn c : columns) {
Field data = (Field) c.getData("field");
String text = data.name;
if ((this.currentColumns.contains(text))/*&&(!currentColumns.isEmpty())*/) { //!this.currentColumns.contains(text)
c.setWidth(0);
m.remove(text);
}
else{
if (c.getWidth()==0){
c.setWidth(100);
}
}
}
}
}