/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.transformation.ui.builder.expression;
import java.util.List;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.teiid.core.designer.util.CoreArgCheck;
import org.teiid.core.designer.util.I18nUtil;
import org.teiid.designer.query.sql.lang.ILanguageObject;
import org.teiid.designer.query.sql.symbol.IFunction;
import org.teiid.designer.transformation.ui.builder.AbstractLanguageObjectEditor;
import org.teiid.query.ui.builder.model.FunctionEditorModel;
import org.teiid.query.ui.builder.model.ILanguageObjectEditorModelListener;
import org.teiid.query.ui.builder.model.LanguageObjectEditorModelEvent;
import org.teiid.query.ui.builder.util.BuilderUtils;
/**
* FunctionEditor
*
* @since 8.0
*/
public class FunctionEditor extends AbstractLanguageObjectEditor {
private static final String PREFIX = I18nUtil.getPropertyPrefix(FunctionEditor.class);
private static final String[] TBL_HDRS = new String[] {Util.getString(PREFIX + "argColumnHdr"), //$NON-NLS-1$
Util.getString(PREFIX + "valueColumnHdr")}; //$NON-NLS-1$
/** Function argument name table column index. */
private static final int ARG_INDEX = 0;
/** Function argumen value table column index. */
private static final int VALUE_INDEX = 1;
private ViewController controller;
FunctionEditorModel model;
private boolean processingEvents = true;
private Combo cbxCategory;
private Combo cbxFunction;
private Composite pnlContent;
private Table table;
private TableViewer viewer;
/**
* Constructs a <code>FunctionEditor</code> using the given model.
*
* @param theParent the parent container
* @param theModel the editor's model
* @throws IllegalArgumentException if any of the parameters are <code>null</code>
*/
public FunctionEditor( Composite theParent,
FunctionEditorModel theModel ) {
super(theParent, IFunction.class, theModel);
// Note: the call to super calls createUi
controller = new ViewController();
model = theModel;
model.addModelListener(controller);
viewer.setInput(model);
cbxCategory.setItems(model.getCategories());
// start the controller
controller.initialize();
}
/**
* @see org.teiid.designer.transformation.ui.builder.ILanguageObjectEditor#acceptFocus()
*/
@Override
public void acceptFocus() {
cbxFunction.setFocus();
}
/**
* @see org.teiid.designer.transformation.ui.builder.AbstractLanguageObjectEditor#createUi(org.eclipse.swt.widgets.Composite)
*/
@Override
protected void createUi( Composite theParent ) {
pnlContent = new Composite(theParent, SWT.NONE);
pnlContent.setLayoutData(new GridData(GridData.FILL_BOTH));
GridLayout layout = new GridLayout();
layout.numColumns = 2;
pnlContent.setLayout(layout);
//
// pnlContent contents
//
Label lblCategory = new Label(pnlContent, SWT.NONE);
lblCategory.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
lblCategory.setText(Util.getString(PREFIX + "lblCategory")); //$NON-NLS-1$
cbxCategory = new Combo(pnlContent, SWT.BORDER | SWT.READ_ONLY);
cbxCategory.setToolTipText(Util.getString(PREFIX + "cbxCategory.tip")); //$NON-NLS-1$
cbxCategory.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
cbxCategory.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected( SelectionEvent theEvent ) {
handleCategorySelected();
}
});
Label lblFunction = new Label(pnlContent, SWT.NONE);
lblFunction.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
lblFunction.setText(Util.getString(PREFIX + "lblFunction")); //$NON-NLS-1$
cbxFunction = new Combo(pnlContent, SWT.BORDER | SWT.READ_ONLY);
cbxFunction.setToolTipText(Util.getString(PREFIX + "cbxFunction.tip")); //$NON-NLS-1$
cbxFunction.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
cbxFunction.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected( SelectionEvent theEvent ) {
handleFunctionSelected();
}
});
int style = SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION | SWT.READ_ONLY;
viewer = new TableViewer(pnlContent, style);
viewer.setContentProvider(new TableContentProvider());
viewer.setLabelProvider(new TableLabelProvider());
table = viewer.getTable();
table.setHeaderVisible(true);
table.setLinesVisible(true);
table.setLayout(new TableLayout());
GridData gd = new GridData(GridData.FILL_BOTH);
gd.horizontalSpan = 2;
table.setLayoutData(gd);
// create columns
for (int i = 0; i < TBL_HDRS.length; i++) {
TableColumn argCol = new TableColumn(table, SWT.CENTER);
argCol.setText(TBL_HDRS[i]);
}
}
void displayCategoryChange() {
String category = model.getCategory();
if (category == null) {
model.setCategory(model.getDefaultCategory());
} else {
if ((cbxCategory.getSelectionIndex() == -1) || !category.equals(cbxCategory.getText())) {
cbxCategory.setText(category);
}
//
// make sure items in combobox are correct
//
String[] functions = model.getFunctions();
String[] items = cbxFunction.getItems();
boolean loadItems = true;
if (functions.length == items.length) {
for (int i = 0; i < functions.length; i++) {
if (!functions[i].equals(items[i])) {
loadItems = true;
break;
}
}
}
if (loadItems) {
processingEvents = false;
cbxFunction.setItems(functions);
processingEvents = true;
}
//
// make sure appropriate function is correct
//
String function = model.getFunctionName();
if (function == null) {
if (cbxFunction.getItemCount() > 0) {
// select first function if no function is set
model.setFunctionName(cbxFunction.getItem(0));
} else {
// no functions found for category
Util.log(IStatus.WARNING, Util.getString(PREFIX + "noFunctionsFound", new Object[] {category})); //$NON-NLS-1$
}
} else {
if ((cbxFunction.getSelectionIndex() == -1) || !cbxFunction.getText().equals(function)) {
processingEvents = false;
model.setFunctionName(function);
processingEvents = true;
}
}
}
}
void displayFunctionChange() {
// only update UI if different function selected
if ((cbxFunction.getSelectionIndex() == -1) || !cbxFunction.getText().equals(model.getFunction().toString())) {
cbxFunction.setText(model.getFunctionName());
cbxFunction.setToolTipText(model.getFunctionDescription());
viewer.refresh();
for (int i = 0; i < TBL_HDRS.length; table.getColumn(i++).pack()) {
}
}
}
void displayLanguageObjectChange() {
displayCategoryChange();
displayFunctionChange();
}
/**
* @see org.teiid.designer.transformation.ui.builder.ILanguageObjectEditor#getTitle()
*/
@Override
public String getTitle() {
return Util.getString(PREFIX + "title"); //$NON-NLS-1$
}
/**
* @see org.teiid.designer.transformation.ui.builder.AbstractLanguageObjectEditor#getToolTipText()
*/
@Override
public String getToolTipText() {
return Util.getString(PREFIX + "tip"); //$NON-NLS-1$
}
/** Handler for function category combobox change. */
void handleCategorySelected() {
model.setCategory(cbxCategory.getText());
}
/** Handler for function combobox change. */
void handleFunctionSelected() {
if (processingEvents) {
model.setFunctionName(cbxFunction.getText());
}
}
/**
* @see org.teiid.designer.transformation.ui.builder.ILanguageObjectEditor#setLanguageObject(org.teiid.query.sql.LanguageObject)
*/
@Override
public void setLanguageObject( ILanguageObject theLanguageObject ) {
if (theLanguageObject == null) {
clear();
} else {
if (!(theLanguageObject instanceof IFunction)) {
CoreArgCheck.isTrue((theLanguageObject instanceof IFunction),
Util.getString(PREFIX + "invalidLanguageObject", //$NON-NLS-1$
new Object[] {theLanguageObject.getClass().getName()}));
}
model.setLanguageObject(theLanguageObject);
}
}
/**
* The <code>ViewController</code> class is a view controller for the <code>FunctionEditor</code>.
*/
class ViewController implements ILanguageObjectEditorModelListener {
public void initialize() {
// set first selection
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
modelChanged(new LanguageObjectEditorModelEvent(model, FunctionEditorModel.CATEGORY));
}
});
}
/**
* @see org.teiid.query.ui.builder.model.ILanguageObjectEditorModelListener#modelChanged(org.teiid.query.ui.builder.model.LanguageObjectEditorModelEvent)
*/
@Override
public void modelChanged( LanguageObjectEditorModelEvent theEvent ) {
String type = theEvent.getType();
if (type.equals(FunctionEditorModel.CATEGORY)) {
displayCategoryChange();
} else if (type.equals(FunctionEditorModel.SELECTED_FUNCTION)) {
displayFunctionChange();
} else if (type.equals(LanguageObjectEditorModelEvent.SAVED)) {
displayLanguageObjectChange();
}
}
}
class TableContentProvider implements IStructuredContentProvider {
/**
* @see org.eclipse.jface.viewers.IContentProvider#dispose()
*/
@Override
public void dispose() {
}
/**
* @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
*/
@Override
public Object[] getElements( Object theInputElement ) {
Object[] result = null;
List args = model.getFunctionArgNames();
if ((args != null) && !args.isEmpty()) {
List argValues = model.getFunctionArgValues();
int numRows = args.size();
result = new Object[numRows];
for (int i = 0; i < numRows; i++) {
result[i] = new TableRow(args.get(i), argValues.get(i));
}
}
return ((args == null) || args.isEmpty()) ? new Object[0] : result;
}
/**
* @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object,
* java.lang.Object)
*/
@Override
public void inputChanged( Viewer theViewer,
Object theOldInput,
Object theNewInput ) {
}
}
class TableLabelProvider extends LabelProvider implements ITableLabelProvider {
/**
* @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
*/
@Override
public Image getColumnImage( Object theElement,
int theColumnIndex ) {
return null;
}
/**
* @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
*/
@Override
public String getColumnText( Object theElement,
int theColumnIndex ) {
TableRow row = (TableRow)theElement;
return row.getColumnText(theColumnIndex);
}
}
class TableRow {
private Object arg;
private Object value;
public TableRow( Object theArgName,
Object theArgValue ) {
arg = theArgName;
value = theArgValue;
}
public String getColumnText( int theIndex ) {
String result = "unknown"; //$NON-NLS-1$
if (theIndex == ARG_INDEX) {
result = arg.toString();
} else if (theIndex == VALUE_INDEX) {
result = (value == null) ? BuilderUtils.UNDEFINED : value.toString();
}
return result;
}
}
}