/* * 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 org.eclipse.swt.SWT; import org.eclipse.swt.custom.StackLayout; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.TraverseEvent; import org.eclipse.swt.events.TraverseListener; import org.eclipse.swt.events.VerifyEvent; import org.eclipse.swt.events.VerifyListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; 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.IConstant; import org.teiid.designer.transformation.ui.builder.AbstractLanguageObjectEditor; import org.teiid.designer.ui.common.util.WidgetUtil; import org.teiid.designer.ui.common.widget.CalendarWidget; import org.teiid.query.ui.builder.model.ConstantEditorModel; import org.teiid.query.ui.builder.model.ILanguageObjectEditorModelListener; import org.teiid.query.ui.builder.model.LanguageObjectEditorModelEvent; import org.teiid.query.ui.builder.util.BuilderUtils; /** * ConstantEditor * * @since 8.0 */ public final class ConstantEditor extends AbstractLanguageObjectEditor { private static final String PREFIX = I18nUtil.getPropertyPrefix(ConstantEditor.class); private Control currentControl; private ViewController controller; ConstantEditorModel model; private StackLayout stackLayout; String validChars; // valid characters for selected type private Combo cbxType; private CalendarWidget dateWidget; private Label lblNull; private Label lblType; private Composite pnlBoolean; private Composite pnlContent; private Composite pnlDate; private Composite pnlNull; private Composite pnlText; private Group pnlValues; private Button rdbFalse; private Button rdbTrue; private Text txfValue; /** * Constructs a <code>ConstantEditor</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 ConstantEditor( Composite theParent, ConstantEditorModel theModel ) { super(theParent, IConstant.class, theModel); controller = new ViewController(); model = theModel; model.addModelListener(controller); // start the controller controller.initialize(); } /** * @see org.teiid.designer.transformation.ui.builder.ILanguageObjectEditor#acceptFocus() */ @Override public void acceptFocus() { if (isConversionType()) { cbxType.setFocus(); } else if (currentControl == pnlNull) { cbxType.setFocus(); } else if (currentControl == pnlBoolean) { if (rdbTrue.getSelection()) { rdbTrue.setFocus(); } else { rdbFalse.setFocus(); } } else if (currentControl == pnlText) { txfValue.setFocus(); } else if (currentControl == pnlDate) { dateWidget.setFocus(); } } private void constructBooleanWidgets() { if (rdbTrue == null) { rdbTrue = new Button(pnlBoolean, SWT.RADIO); rdbTrue.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.CENTER)); rdbTrue.setText(Util.getString(PREFIX + "rdbTrue")); //$NON-NLS-1$ rdbTrue.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent theEvent ) { handleTrueSelected(); } }); rdbTrue.setSelection(true); rdbFalse = new Button(pnlBoolean, SWT.RADIO); rdbFalse.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.CENTER)); rdbFalse.setText(Util.getString(PREFIX + "rdbFalse")); //$NON-NLS-1$ rdbFalse.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent theEvent ) { handleFalseSelected(); } }); pnlBoolean.pack(); } } private void constructDateWidgets() { if (dateWidget == null) { dateWidget = new CalendarWidget(pnlDate, SWT.NONE, false); dateWidget.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent e ) { handleDateChanged(); } }); dateWidget.setLayoutData(new GridData()); pnlDate.pack(); } } private void constructNullWidgets() { if (lblNull == null) { lblNull = new Label(pnlNull, SWT.BORDER); lblNull.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); lblNull.setText(Util.getString(PREFIX + "txfNull")); //$NON-NLS-1$ pnlNull.pack(); } } private void constructTextWidgets() { if (txfValue == null) { txfValue = new Text(pnlText, SWT.BORDER); txfValue.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); txfValue.addModifyListener(new ModifyListener() { @Override public void modifyText( ModifyEvent theEvent ) { handleTextChange(); } }); txfValue.addVerifyListener(new VerifyListener() { @Override public void verifyText( VerifyEvent theEvent ) { String text = theEvent.text; if ((text != null) && (text.length() > 0)) { for (int size = text.length(), i = 0; i < size; i++) { if ((validChars != null) && (validChars.indexOf(text.charAt(i)) == -1)) { theEvent.doit = false; break; } else if (!model.isValidValue(text)) { theEvent.doit = false; break; } } } } }); txfValue.addTraverseListener(new TraverseListener() { @Override public void keyTraversed( TraverseEvent theEvent ) { // stops the enter key from putting in invisible characters if (theEvent.detail == SWT.TRAVERSE_RETURN) { theEvent.detail = SWT.TRAVERSE_NONE; theEvent.doit = true; } } }); pnlText.pack(); } } /** * @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 // lblType = new Label(pnlContent, SWT.NONE); lblType.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); lblType.setText(Util.getString(PREFIX + "lblType")); //$NON-NLS-1$ cbxType = new Combo(pnlContent, SWT.BORDER | SWT.READ_ONLY); cbxType.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); cbxType.setItems(BuilderUtils.getAllTypes().toArray(new String[0])); cbxType.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent theEvent ) { handleTypeSelected(); } }); pnlValues = new Group(pnlContent, SWT.NONE); pnlValues.setText(Util.getString(PREFIX + "pnlValues")); //$NON-NLS-1$ stackLayout = new StackLayout(); pnlValues.setLayout(stackLayout); GridData gd = new GridData(GridData.FILL_BOTH); gd.horizontalSpan = 2; pnlValues.setLayoutData(gd); // // pnlValues contents // pnlText = new Composite(pnlValues, SWT.NONE); pnlText.setLayout(new GridLayout()); pnlText.setLayoutData(new GridData(GridData.FILL_BOTH)); // contents of pnlText created in constructTextWidgets() pnlNull = new Composite(pnlValues, SWT.NONE); pnlNull.setLayout(new GridLayout()); pnlNull.setLayoutData(new GridData(GridData.FILL_BOTH)); // contents of pnlNull created in constructNullWidgets() pnlBoolean = new Composite(pnlValues, SWT.NONE); pnlBoolean.setLayout(new GridLayout()); pnlBoolean.setLayoutData(new GridData(GridData.FILL_BOTH)); // contents of pnlBoolean created in constructBooleanWidgets() pnlDate = new Composite(pnlValues, SWT.NONE); pnlDate.setLayout(new GridLayout()); pnlDate.setLayoutData(new GridData(GridData.FILL_BOTH)); // contents of pnlDate created in constructDateWidgets() } void displayBooleanTypeUi() { normalizeTypes(); boolean value = model.getBoolean(); constructBooleanWidgets(); if (rdbTrue.getSelection() != value) { if (model.getBoolean()) { WidgetUtil.selectRadioButton(rdbTrue); } else { WidgetUtil.selectRadioButton(rdbFalse); } } showControl(pnlBoolean); } void displayConversionTypeUi() { normalizeTypes(); showValueLabel(false); } void displayDateTypeUi() { normalizeTypes(); constructDateWidgets(); dateWidget.setValue(model.getDate()); dateWidget.showCalendar(true); dateWidget.showTime(false); pnlDate.pack(); showControl(pnlDate); } void displayNullTypeUi() { normalizeTypes(); constructNullWidgets(); showControl(pnlNull); } void displayTextTypeUi() { normalizeTypes(); String value = model.getText(); if (value == null) { value = ""; //$NON-NLS-1$ } constructTextWidgets(); if (!txfValue.getText().equals(value)) { txfValue.setText(value); // causes caret to be placed at the beginning txfValue.setSelection(value.length()); // place caret at end } showControl(pnlText); } void displayTimeTypeUi() { normalizeTypes(); constructDateWidgets(); dateWidget.setValue(model.getTime()); dateWidget.showCalendar(false); dateWidget.showTime(true); pnlDate.pack(); showControl(pnlDate); } void displayTimestampTypeUi() { normalizeTypes(); constructDateWidgets(); dateWidget.setValue(model.getTimestamp()); dateWidget.showCalendar(true); dateWidget.showTime(true); pnlDate.pack(); showControl(pnlDate); } void displayTypeUi() { normalizeTypes(); constructTextWidgets(); String modelType = model.getType(); txfValue.setTextLimit(BuilderUtils.getTextLimit(modelType)); cbxType.setText(modelType); } /** * @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$ } void handleDateChanged() { if (dateWidget.isDateWidget()) { model.setDate(dateWidget.getDate()); } else if (dateWidget.isTimeWidget()) { model.setTime(dateWidget.getTime()); } else if (dateWidget.isTimestampWidget()) { model.setTimestamp(dateWidget.getTimestamp()); } } void handleFalseSelected() { // only care about selection, not deselection if (rdbFalse.getSelection()) { model.setBoolean(false); } } void handleTextChange() { // the text entered is set into the model. // this causes the view controller to be modified of a text change which sets the text field's text model.setText(txfValue.getText()); } void handleTrueSelected() { // only care about selection, not deselection if (rdbTrue.getSelection()) { model.setBoolean(true); } } void handleTypeSelected() { int index = cbxType.getSelectionIndex(); model.setType(cbxType.getItem(index)); } public boolean isConversionType() { return model.isConversionType(); } /** * The set of available types are different when the constant is a conversion type and when it is not. This method makes sure * the types are correct. */ private void normalizeTypes() { // processTypeChange = false; String selection = cbxType.getText(); // save current selection boolean conversionType = isConversionType(); for (String invalidType : BuilderUtils.getInvalidTypes()) { if (conversionType) { if (cbxType.indexOf(invalidType) != -1) { cbxType.remove(invalidType); } else { // assume if one type is not there then all of them are not there break; } } else { if (cbxType.indexOf(invalidType) == -1) { cbxType.add(invalidType); } else { // assume if one type is there then all of them are there break; } } } cbxType.setText(selection); // set back to saved selection // processTypeChange = true; } /** * @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 { CoreArgCheck.isTrue((theLanguageObject instanceof IConstant), Util.getString(PREFIX + "invalidLanguageObject", //$NON-NLS-1$ new Object[] {theLanguageObject.getClass().getName()})); model.setLanguageObject(theLanguageObject); } } private void showControl( Control theControl ) { showValueLabel(true); if (currentControl != theControl) { currentControl = theControl; stackLayout.topControl = currentControl; pnlValues.layout(); } acceptFocus(); } /** The value widgets are shown when not displaying a conversion type. */ private void showValueLabel( boolean theShowFlag ) { pnlValues.setVisible(theShowFlag); } /** * The <code>ViewController</code> class is a view controller for the <code>ConstantEditor</code>. */ class ViewController implements ILanguageObjectEditorModelListener { public void initialize() { // set first selection Display.getDefault().asyncExec(new Runnable() { @Override public void run() { modelChanged(new LanguageObjectEditorModelEvent(model, ConstantEditorModel.TYPE)); } }); } /** * @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(LanguageObjectEditorModelEvent.SAVED)) { modelChanged(new LanguageObjectEditorModelEvent(model, ConstantEditorModel.TYPE)); } else if (type.equals(ConstantEditorModel.TYPE)) { displayTypeUi(); if (model.isConversionType()) { displayConversionTypeUi(); } else if (model.isText()) { modelChanged(new LanguageObjectEditorModelEvent(model, ConstantEditorModel.TEXT)); } else if (model.isBoolean()) { modelChanged(new LanguageObjectEditorModelEvent(model, ConstantEditorModel.BOOLEAN)); } else if (model.isNull()) { modelChanged(new LanguageObjectEditorModelEvent(model, ConstantEditorModel.NULL)); } else if (model.isDate()) { modelChanged(new LanguageObjectEditorModelEvent(model, ConstantEditorModel.DATE)); } else if (model.isTime()) { modelChanged(new LanguageObjectEditorModelEvent(model, ConstantEditorModel.TIME)); } else if (model.isTimestamp()) { modelChanged(new LanguageObjectEditorModelEvent(model, ConstantEditorModel.TIMESTAMP)); } } else if (type.equals(ConstantEditorModel.TEXT)) { displayTextTypeUi(); } else if (type.equals(ConstantEditorModel.BOOLEAN)) { displayBooleanTypeUi(); } else if (type.equals(ConstantEditorModel.NULL)) { displayNullTypeUi(); } else if (type.equals(ConstantEditorModel.DATE)) { displayDateTypeUi(); } else if (type.equals(ConstantEditorModel.TIME)) { displayTimeTypeUi(); } else if (type.equals(ConstantEditorModel.TIMESTAMP)) { displayTimestampTypeUi(); } } } }