/* * 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; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.custom.CTabFolder; import org.eclipse.swt.custom.CTabItem; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.custom.ViewForm; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; import org.teiid.core.designer.util.CoreArgCheck; import org.teiid.core.designer.util.CoreStringUtil; import org.teiid.core.designer.util.I18nUtil; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.query.IQueryService; import org.teiid.designer.query.sql.ISQLStringVisitor; import org.teiid.designer.query.sql.lang.ILanguageObject; import org.teiid.designer.transformation.ui.UiConstants; import org.teiid.designer.transformation.ui.builder.actions.DeleteViewerObjectAction; import org.teiid.designer.transformation.ui.editors.sqleditor.SqlDisplayPanel; import org.teiid.designer.ui.common.util.WidgetFactory; import org.teiid.designer.ui.common.widget.Dialog; import org.teiid.query.ui.builder.model.ILanguageObjectEditorModelListener; import org.teiid.query.ui.builder.model.LanguageObjectEditorModelEvent; import org.teiid.query.ui.builder.util.BuilderUtils; /** * AbstractLanguageObjectBuilder * * @since 8.0 */ public abstract class AbstractLanguageObjectBuilder extends Dialog implements UiConstants { // ///////////////////////////////////////////////////////////////////////////////////////////// // CONSTANTS // ///////////////////////////////////////////////////////////////////////////////////////////// private static final String PREFIX = I18nUtil.getPropertyPrefix(AbstractLanguageObjectBuilder.class); // ///////////////////////////////////////////////////////////////////////////////////////////// // FIELDS // ///////////////////////////////////////////////////////////////////////////////////////////// private IAction deleteAction; private ILanguageObjectEditor editor; private ILanguageObject savedSelection; protected ILanguageObject savedLangObj; // ///////////////////////////////////////////////////////////////////////////////////////////// // CONTROLS // ///////////////////////////////////////////////////////////////////////////////////////////// protected Button btnSet; protected Button btnReset; private Label lblTitle; private Composite pnlEditor; private Composite pnlEditorDetail; LanguageObjectBuilderTreeViewer treeViewer; private SqlDisplayPanel currentSql; private SqlDisplayPanel originalSql; private CLabel originalLanguageObjLabel; // ///////////////////////////////////////////////////////////////////////////////////////////// // CONSTRUCTORS // ///////////////////////////////////////////////////////////////////////////////////////////// protected AbstractLanguageObjectBuilder( Shell theParent, String theTitle ) { super(theParent, theTitle); } // ///////////////////////////////////////////////////////////////////////////////////////////// // METHODS // ///////////////////////////////////////////////////////////////////////////////////////////// @Override public void create() { super.create(); editor = createEditor(pnlEditorDetail); editor.getModel().addModelListener(new ILanguageObjectEditorModelListener() { @Override public void modelChanged( LanguageObjectEditorModelEvent theEvent ) { handleModelChanged(); } }); lblTitle.setText(editor.getTitle()); Composite pnlEditorButtons = new Composite(pnlEditor, SWT.NONE); pnlEditorButtons.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_CENTER)); pnlEditorButtons.setLayout(new GridLayout()); // // pnlEditorButtons contents // btnSet = new Button(pnlEditorButtons, SWT.NONE); btnSet.setEnabled(false); btnSet.setText(Util.getString(PREFIX + "btnSet")); //$NON-NLS-1$ btnSet.setToolTipText(Util.getString(PREFIX + "btnSet.tip")); //$NON-NLS-1$ btnSet.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent theEvent ) { handleSetSelected(); } }); btnReset = new Button(pnlEditorButtons, SWT.NONE); btnReset.setEnabled(false); btnReset.setText(Util.getString(PREFIX + "btnReset")); //$NON-NLS-1$ btnReset.setToolTipText(Util.getString(PREFIX + "btnReset.tip")); //$NON-NLS-1$ btnReset.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent theEvent ) { handleResetSelected(); } }); setLanguageObject(null); // needed to establish the viewer input // select root tree node after all construction is finished Display.getDefault().asyncExec(new Runnable() { @Override public void run() { treeViewer.selectRoot(); } }); } /* (non-Javadoc) * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite) */ @Override protected Control createDialogArea( Composite theParent ) { originalLanguageObjLabel = WidgetFactory.createLabel(theParent, CoreStringUtil.Constants.EMPTY_STRING); Composite pnlContents = (Composite)super.createDialogArea(theParent); // // main panel contents // CTabFolder tabFolder = WidgetFactory.createTabFolder(pnlContents); // // tabFolder contents - 2 tabs (Tree, SQL Text), each with a splitter // CTabItem treeTab = WidgetFactory.createTab(tabFolder, Util.getString(PREFIX + "treeTab")); //$NON-NLS-1$ treeTab.setToolTipText(Util.getString(PREFIX + "treeTab.tip")); //$NON-NLS-1$ SashForm treeTabSash = new SashForm(tabFolder, SWT.VERTICAL); treeTabSash.setLayoutData(new GridData(GridData.FILL_BOTH)); treeTab.setControl(treeTabSash); CTabItem sqlTab = WidgetFactory.createTab(tabFolder, Util.getString(PREFIX + "sqlTab")); //$NON-NLS-1$ sqlTab.setToolTipText(Util.getString(PREFIX + "sqlTab.tip")); //$NON-NLS-1$ SashForm sqlTabSash = new SashForm(tabFolder, SWT.VERTICAL); sqlTabSash.setLayoutData(new GridData(GridData.FILL_BOTH)); sqlTab.setControl(sqlTabSash); // // treeTab contents // ViewForm formTree = new ViewForm(treeTabSash, SWT.BORDER); Composite pnlTree = new Composite(formTree, SWT.NO_TRIM); formTree.setContent(pnlTree); GridLayout layout = new GridLayout(); layout.marginWidth = 0; layout.marginHeight = 0; pnlTree.setLayout(layout); pnlTree.setLayoutData(new GridData(GridData.FILL_BOTH)); ViewForm formEditor = new ViewForm(treeTabSash, SWT.BORDER); pnlEditor = new Composite(formEditor, SWT.NO_TRIM); formEditor.setContent(pnlEditor); pnlEditor.setLayoutData(new GridData(GridData.FILL_BOTH)); lblTitle = new Label(formEditor, SWT.CENTER); lblTitle.setBackground(BuilderUtils.COLOR_HIGHLIGHT); formEditor.setTopLeft(lblTitle); treeTabSash.setWeights(new int[] {30, 70}); // // sqlTab contents // ViewForm formCurrentSql = new ViewForm(sqlTabSash, SWT.BORDER); ViewForm formOriginalSql = new ViewForm(sqlTabSash, SWT.BORDER); // // formCurrentSql contents // Composite pnlCurrentSql = new Composite(formCurrentSql, SWT.NONE); formCurrentSql.setContent(pnlCurrentSql); pnlCurrentSql.setLayout(new GridLayout()); pnlCurrentSql.setLayoutData(new GridData(GridData.FILL_BOTH)); currentSql = new SqlDisplayPanel(pnlCurrentSql); currentSql.setLayoutData(new GridData(GridData.FILL_BOTH)); CLabel lblCurrent = new CLabel(formCurrentSql, SWT.NONE); lblCurrent.setBackground(BuilderUtils.COLOR_HIGHLIGHT); lblCurrent.setText(Util.getString(PREFIX + "lblCurrent")); //$NON-NLS-1$ lblCurrent.setToolTipText(Util.getString(PREFIX + "lblCurrent.tip")); //$NON-NLS-1$ formCurrentSql.setTopLeft(lblCurrent); // // formOriginalSql contents // Composite pnlOriginalSql = new Composite(formOriginalSql, SWT.NONE); formOriginalSql.setContent(pnlOriginalSql); pnlOriginalSql.setLayout(new GridLayout()); pnlOriginalSql.setLayoutData(new GridData(GridData.FILL_BOTH)); originalSql = new SqlDisplayPanel(pnlOriginalSql); originalSql.setLayoutData(new GridData(GridData.FILL_BOTH)); CLabel lblOriginal = new CLabel(formOriginalSql, SWT.NONE); lblOriginal.setBackground(BuilderUtils.COLOR_HIGHLIGHT); lblOriginal.setText(Util.getString(PREFIX + "lblOriginal")); //$NON-NLS-1$ lblOriginal.setToolTipText(Util.getString(PREFIX + "lblOriginal.tip")); //$NON-NLS-1$ formOriginalSql.setTopLeft(lblOriginal); // // pnlTree contents - 2 columns (tree viewer, button panel) // layout = new GridLayout(); layout.numColumns = 2; layout.marginHeight = 0; layout.marginWidth = 0; pnlTree.setLayout(layout); treeViewer = new LanguageObjectBuilderTreeViewer(pnlTree); treeViewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged( SelectionChangedEvent theEvent ) { handleTreeSelection(); } }); MenuManager menuMgr = new MenuManager(); menuMgr.setRemoveAllWhenShown(true); menuMgr.addMenuListener(new IMenuListener() { @Override public void menuAboutToShow( IMenuManager theMenuMgr ) { fillContextMenu(theMenuMgr); } }); treeViewer.getTree().setMenu(menuMgr.createContextMenu(treeViewer.getTree())); Composite pnlButtons = new Composite(pnlTree, SWT.NONE); pnlButtons.setLayout(new GridLayout()); createTreeButtons(pnlButtons); // // pnlEditor contents // layout = new GridLayout(); layout.numColumns = 2; pnlEditor.setLayout(layout); pnlEditorDetail = new Composite(pnlEditor, SWT.NONE); pnlEditorDetail.setLayoutData(new GridData(GridData.FILL_BOTH)); pnlEditorDetail.setLayout(new GridLayout()); return pnlContents; } protected abstract ILanguageObjectEditor createEditor( Composite theParent ); /** * Creates buttons that interact with the tree. * * @param theParent the panel where the buttons are contained */ protected void createTreeButtons( Composite theParent ) { Runnable deleteRunner = new Runnable() { @Override public void run() { handleDeleteSelected(); } }; deleteAction = new DeleteViewerObjectAction(theParent, deleteRunner); } protected void fillContextMenu( IMenuManager theMenuMgr ) { theMenuMgr.add(deleteAction); } public ILanguageObjectEditor getEditor() { return editor; } /* (non-Javadoc) * @see org.teiid.query.ui.builder.ILanguageObjectInputProvider#getLanguageObject() */ public ILanguageObject getLanguageObject() { return treeViewer.getLanguageObject(); } /** * Gets the saved <code>LanguageObject</code>. * * @return the saved <code>LanguageObject</code> or <code>null</code> */ protected ILanguageObject getSavedLanguageObject() { return savedLangObj; } /** * Gets a title for the builder. Title is appropriate for use as a dialog title. * * @return the builder title */ @Override public abstract String getTitle(); protected LanguageObjectBuilderTreeViewer getTreeViewer() { return treeViewer; } protected void handleDeleteSelected() { editor.clear(); treeViewer.deleteSelection(); // update SQL text setCurrentSql(treeViewer.getLanguageObject()); editor.acceptFocus(); } void handleModelChanged() { boolean isEnabled = false; boolean isComplete = false; boolean hasChanged = false; isEnabled = editor.isEnabled(); if (isEnabled) { isComplete = editor.isComplete(); } if (isComplete) { hasChanged = editor.hasChanged(); } boolean state = (isEnabled && isComplete && hasChanged); btnSet.setEnabled(state); btnReset.setEnabled(state); setCurrentSql(treeViewer.getLanguageObject()); // set enable/disable status of buttons setEnabledStatus(); } protected void handleResetSelected() { editor.reset(); // put focus back on editor from the reset button editor.acceptFocus(); } protected void handleSetSelected() { editor.save(); // need the editor's language object in order to update tree. // the language object should never be null. if it was this handler should not have been called ILanguageObject langObj = editor.getLanguageObject(); CoreArgCheck.isNotNull(langObj, Util.getString(PREFIX + "nullLangObj", //$NON-NLS-1$ new Object[] {"handleSetSelected"})); //$NON-NLS-1$ // update tree treeViewer.modifySelectedItem(langObj, false); // update SQL text setCurrentSql(treeViewer.getLanguageObject()); // put focus back on editor from the set button editor.acceptFocus(); } protected void handleTreeSelection() { IStructuredSelection selection = (IStructuredSelection)treeViewer.getSelection(); Object selectedObj = selection.getFirstElement(); if (selectedObj == null) { savedSelection = null; if (editor.isEnabled()) { editor.setEnabled(false); } } else { // selection with either be a LanguageObject or an Undefined object (String) savedSelection = (selectedObj instanceof ILanguageObject) ? (ILanguageObject)selectedObj : null; } setEditorLanguageObject(savedSelection); // set enable/disable status of buttons setEnabledStatus(); } protected boolean isTreeSelectionRoot() { boolean isRoot = false; IStructuredSelection selection = (IStructuredSelection)treeViewer.getSelection(); if (selection.size() > 0) { Tree tree = treeViewer.getTree(); // We are assuming that the tree is single-selection. TreeItem treeItem = tree.getSelection()[0]; TreeItem parentItem = treeItem.getParentItem(); isRoot = (parentItem == null); } return isRoot; } protected void setCurrentSql( ILanguageObject theLangObj ) { IQueryService queryService = ModelerCore.getTeiidQueryService(); ISQLStringVisitor visitor = queryService.getSQLStringVisitor(); currentSql.setText(visitor.returnSQLString(theLangObj)); } protected void setEditorLanguageObject( ILanguageObject theEditorLangObj ) { getEditor().setLanguageObject(savedSelection); if (!editor.isEnabled()) { editor.setEnabled(true); } } protected void setEnabledStatus() { // // set enabled status of delete button // boolean canDelete = treeViewer.canDeleteSelection(); if (canDelete) { if (!deleteAction.isEnabled()) { deleteAction.setEnabled(true); } } else { if (deleteAction.isEnabled()) { deleteAction.setEnabled(false); } } // // set enabled status of OK button // Button btnOk = getButton(OK); boolean enable = treeViewer.isComplete(); if (btnOk.isEnabled() != enable) { btnOk.setEnabled(enable); } } public void setLanguageObject( ILanguageObject theLangObj ) { // language object must be cloned here so that the original isn't modified. // this prevents the original from being modified even if the user cancels out of the builder. ILanguageObject langObj = (theLangObj == null) ? null : (ILanguageObject)theLangObj.clone(); savedLangObj = langObj; setOriginalSql(langObj); setCurrentSql(langObj); treeViewer.setLanguageObject(langObj); treeViewer.selectRoot(); treeViewer.expandAll(); // Defect 22003 - needed a context for the original expression // Providing a Lable at the top of the dialog. String labelText = Util.getString(PREFIX + "initialExpression") + //$NON-NLS-1$ CoreStringUtil.Constants.DBL_SPACE + CoreStringUtil.Constants.DBL_SPACE + Util.getString(PREFIX + "undefined"); //$NON-NLS-1$ if (savedLangObj != null) { String loString = savedLangObj.toString(); if (loString.length() > 50) { loString = loString.substring(0, 50) + "..."; //$NON-NLS-1$ } labelText = Util.getString(PREFIX + "initialExpression") + //$NON-NLS-1$ CoreStringUtil.Constants.DBL_SPACE + CoreStringUtil.Constants.DBL_SPACE + loString; } if (originalLanguageObjLabel != null) { originalLanguageObjLabel.setText(labelText); originalLanguageObjLabel.getParent().layout(); } // select root tree node Display.getDefault().asyncExec(new Runnable() { @Override public void run() { treeViewer.selectRoot(); } }); } protected void setOriginalSql( ILanguageObject theLangObj ) { IQueryService queryService = ModelerCore.getTeiidQueryService(); ISQLStringVisitor visitor = queryService.getSQLStringVisitor(); originalSql.setText(visitor.returnSQLString(theLangObj)); } }