package org.marketcetera.photon.views;
import java.io.InputStream;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.part.ViewPart;
import org.marketcetera.photon.EclipseUtils;
import com.swtworkbench.community.xswt.XSWT;
import com.swtworkbench.community.xswt.layoutbuilder.FormToolkitLayoutBuilder;
/**
* Abstract base class for Eclipse views built from an XSWT descriptor file.
* This class takes care of instantiating the UI, setting up the databinding
* context, and provides some utility classes for "finishing" the UI.
*
* The type parameter indicates the type of object that should be returned
* from the call to {@link XSWT#parse(Object, Class)}, and should correspond
* to the value returned by {@link #getXSWTInterfaceClass()}.
*
*
* Subclassers should implement the {@link #finishUI()} callback in order
* to perform any "cleanup" work necessary after the XSWT file has been loaded
* and instantiated, for example hooking up event listeners.
*
* @author gmiller
*
* @param <T>
*/
public abstract class XSWTView<T> extends ViewPart {
private DataBindingContext dataBindingContext;
private T xswtView;
@Override
public void dispose() {
dataBindingContext.dispose();
super.dispose();
}
@SuppressWarnings("unchecked") //$NON-NLS-1$
@Override
public void createPartControl(Composite parent) {
try {
XSWT xswt = XSWT.create(getXSWTResourceStream());
new FormToolkitLayoutBuilder(xswt);
xswtView = (T)xswt.parse(parent, getXSWTInterfaceClass());
dataBindingContext = new DataBindingContext();
} catch (Exception e) {
throw new RuntimeException(e);
}
finishUI();
}
/**
* Get the class of the interface type that should be returned
* from {@link XSWT#parse(Object, Class)}
*
* @return the interface class
*/
protected abstract Class<? extends T> getXSWTInterfaceClass();
/**
* Subclasses are recommended to "post-process" the UI,
* in order to take care of tasks like event listener connection,
* fine-tuning of UI components, and other tasks that require
* a real programming language (not XSWT).
*/
protected abstract void finishUI();
/**
* The input stream from which to load the XSWT xml
* file.
*
* @return the input stream
*/
protected abstract InputStream getXSWTResourceStream();
/**
* This utility method sets the "size" hint of a control
* based on the size of the specified number of characters in the
* default font for the control.
*
* @param aControl the control to size
* @param charSize the recommended width in characters
*/
protected void updateSize(Control aControl, int charSize) {
Point sizeHint = EclipseUtils.getTextAreaSize(aControl,
null, charSize, 1.0);
Object layoutData = aControl.getLayoutData();
if (layoutData instanceof GridData){
((GridData)layoutData).widthHint = sizeHint.x;
((GridData)layoutData).heightHint = sizeHint.y;
} else if (layoutData instanceof RowData){
((RowData)layoutData).width = sizeHint.x;
((RowData)layoutData).height = sizeHint.y;
}
}
/**
* This utility method loops through the columns in a table
* and calls {@link TableColumn#pack()}
* @param table the table to pack
*/
public static void packColumns(Table table) {
for (TableColumn column : table.getColumns()) {
column.pack();
}
}
/**
* Return the {@link DataBindingContext} for this view.
* @return the DataBindingContext
*/
public DataBindingContext getDataBindingContext() {
return dataBindingContext;
}
/**
* Clear the {@link DataBindingContext} for this view of all bindings.
*/
public void clearDataBindingContext() {
Realm origRealm = dataBindingContext.getValidationRealm();
try {
dataBindingContext.dispose();
} catch (Exception ex){
}
dataBindingContext = new DataBindingContext(origRealm);
}
/**
* Return the XSWT proxy object.
*
* @return the XSWT proxy object
*/
public T getXSWTView() {
return xswtView;
}
}