/* * 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.modelgenerator.wsdl.ui.wizards.soap.panels; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableLayout; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.TreeEditor; import org.eclipse.swt.events.FocusAdapter; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.ui.actions.TextActionHandler; import org.teiid.designer.modelgenerator.wsdl.ui.ModelGeneratorWsdlUiConstants; import org.teiid.designer.modelgenerator.wsdl.ui.util.ModelGeneratorWsdlUiUtil; import org.teiid.designer.modelgenerator.wsdl.ui.wizards.soap.AttributeInfo; import org.teiid.designer.modelgenerator.wsdl.ui.wizards.soap.ColumnInfo; import org.teiid.designer.modelgenerator.wsdl.ui.wizards.soap.OperationsDetailsPage; import org.teiid.designer.modelgenerator.wsdl.ui.wizards.soap.ProcedureInfo; import org.teiid.designer.query.proc.wsdl.IWsdlAttributeInfo; /** * @since 8.0 */ public class EditElementsPanel { private final Image XSD_ELEMENT_ICON_IMG = ModelGeneratorWsdlUiUtil.getImage(ModelGeneratorWsdlUiConstants.Images.XSD_ELEMENT_ICON); private final Image XSD_ATTRIBUTE_ICON_IMG = ModelGeneratorWsdlUiUtil.getImage(ModelGeneratorWsdlUiConstants.Images.XSD_ATTRIBUTE_ICON); TreeViewer columnsViewer; ProcedureInfo procedureInfo; int type; TreeEditor treeEditor; Text textEditor; Composite textEditorParent; TextActionHandler textActionHandler; Object selectedObject; TreeItem[] cachedSelection; final OperationsDetailsPage detailsPage; public EditElementsPanel(Composite parent, int style, int type, OperationsDetailsPage detailsPage) { super(); this.type = type; this.detailsPage = detailsPage; createPanel(parent); } public ProcedureInfo getProcedureInfo() { return this.procedureInfo; } public void setProcedureInfo(ProcedureInfo info) { this.procedureInfo = info; this.columnsViewer.setInput(this.procedureInfo); refresh(); } private void createPanel(Composite parent) { Tree table = new Tree(parent, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); table.setHeaderVisible(true); table.setLinesVisible(true); table.setLayout(new TableLayout()); GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); gd.heightHint = 80; table.setLayoutData(gd); this.columnsViewer = new TreeViewer(table); this.columnsViewer.getControl().setLayoutData(gd); treeEditor = new TreeEditor(columnsViewer.getTree()); ColumnDataTreeProvider provider = new ColumnDataTreeProvider(); this.columnsViewer.setContentProvider(provider); this.columnsViewer.setLabelProvider(provider); this.columnsViewer.setAutoExpandLevel(3); this.columnsViewer.addDoubleClickListener(new IDoubleClickListener() { @Override public void doubleClick(DoubleClickEvent event) { renameInline(); } }); this.columnsViewer.getTree().addMouseListener(new MouseAdapter() { @Override public void mouseDown( MouseEvent theEvent ) { if (theEvent.button == 1 ) { if (isTextEditorActive() && selectedObject != null) { saveChangesAndDispose(selectedObject); } } } }); } public void refresh() { this.columnsViewer.refresh(); this.columnsViewer.expandAll(); } public void refresh(Object element) { this.columnsViewer.refresh(element); } public void addSelectionListener(ISelectionChangedListener listener) { this.columnsViewer.addSelectionChangedListener(listener); } public Object getSelectedObject() { IStructuredSelection selection = (IStructuredSelection) this.columnsViewer.getSelection(); for (Object obj : selection.toArray()) { return obj; } return null; } public ColumnInfo getSelectedColumn() { IStructuredSelection selection = (IStructuredSelection) this.columnsViewer.getSelection(); for (Object obj : selection.toArray()) { if( obj instanceof ColumnInfo ) { return (ColumnInfo)obj; } } return null; } public int getSelectedIndex() { TreeItem[] selectedItems = columnsViewer.getTree().getSelection(); if( selectedItems.length > 0 ) { int i=0; for( TreeItem item : columnsViewer.getTree().getItems()) { if( selectedItems[0] == item ) { return i; } } } return -1; } public void selectRow(int index) { if (index > -1) { TreeItem item = columnsViewer.getTree().getItem(index); columnsViewer.getTree().select(item); } else { columnsViewer.setSelection(new StructuredSelection()); } } private void notifyColumnDataChanged() { this.detailsPage.notifyColumnDataChanged(); } public void setEnabled(boolean enable) { columnsViewer.getTree().setEnabled(enable); } class ColumnDataTreeProvider implements ITreeContentProvider, ILabelProvider { @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { // NO OP } @Override public Object[] getElements(Object inputElement) { if( inputElement instanceof ProcedureInfo ) { if (type == ProcedureInfo.TYPE_BODY) { return procedureInfo.getBodyColumnInfoList(); } else { return procedureInfo.getHeaderColumnInfoList(); } } return new Object[0]; } @Override public Object[] getChildren(Object parentElement) { if( parentElement instanceof ColumnInfo ) { return ((ColumnInfo)parentElement).getAttributeInfoArray(); } return null; } @Override public boolean hasChildren(Object element) { if( element instanceof ProcedureInfo ) { if (type == ProcedureInfo.TYPE_BODY) { return procedureInfo.getBodyColumnInfoList().length > 0; } else { return procedureInfo.getHeaderColumnInfoList().length > 0; } } else if( element instanceof ColumnInfo ) { return ((ColumnInfo)element).getAttributeInfoArray().length > 0; } return false; } @Override public Object getParent( Object element ) { return null; } @Override public boolean isLabelProperty(Object element, String property) { // NO OP return false; } @Override public Image getImage(Object element) { if (element instanceof ColumnInfo) { return XSD_ELEMENT_ICON_IMG; } else if( element instanceof IWsdlAttributeInfo ) { return XSD_ATTRIBUTE_ICON_IMG; } return null; } @Override public String getText(Object element) { if (element instanceof ColumnInfo) { return ((ColumnInfo) element).getName(); } else if( element instanceof IWsdlAttributeInfo ) { return ((IWsdlAttributeInfo) element).getSignature(); } return null; } @Override public void addListener( ILabelProviderListener listener ) { // NO OP } @Override public void removeListener( ILabelProviderListener listener ) { // NO OP } @Override public void dispose() { // NO OP } } private void renameInline() { Object obj = getSelectedObject(); selectedObject = obj; cachedSelection = columnsViewer.getTree().getSelection(); // Make sure text editor is created only once. Simply reset text // editor when action is executed more than once. Fixes bug 22269. if (textEditorParent == null) { createTextEditor(obj); } String name = null; if( obj instanceof ColumnInfo ) { name = ((ColumnInfo)obj).getName(); } else if( obj instanceof IWsdlAttributeInfo ) { name = ((IWsdlAttributeInfo)obj).getAlias(); } if (name != null) { textEditor.setText(name); } // Open text editor with initial size. textEditorParent.setVisible(true); Point textSize = textEditor.computeSize(SWT.DEFAULT, SWT.DEFAULT); textSize.x += textSize.y; // Add extra space for new characters. Point parentSize = textEditorParent.getSize(); textEditor.setBounds(2, 1, Math.min(textSize.x, parentSize.x - 4), parentSize.y - 2); textEditorParent.redraw(); textEditor.selectAll(); textEditor.setFocus(); } private void createTextEditor( final Object obj ) { // Create text editor parent. This draws a nice bounding rect. textEditorParent = createEditorParent(); textEditorParent.setVisible(false); textEditorParent.addListener(SWT.Paint, new Listener() { @Override public void handleEvent( Event e ) { Point textSize = textEditor.getSize(); Point parentSize = textEditorParent.getSize(); e.gc.drawRectangle(0, 0, Math.min(textSize.x + 4, parentSize.x - 1), parentSize.y - 1); } }); // Create inner text editor. textEditor = new Text(textEditorParent, SWT.NONE); textEditorParent.setBackground(textEditor.getBackground()); textEditor.addListener(SWT.Modify, new Listener() { @Override public void handleEvent( Event e ) { Point textSize = textEditor.computeSize(SWT.DEFAULT, SWT.DEFAULT); textSize.x += textSize.y; // Add extra space for new characters. Point parentSize = textEditorParent.getSize(); textEditor.setBounds(2, 1, Math.min(textSize.x, parentSize.x - 4), parentSize.y - 2); textEditorParent.redraw(); } }); textEditor.addListener(SWT.Traverse, new Listener() { @Override public void handleEvent( Event event ) { // Workaround for Bug 20214 due to extra // traverse events switch (event.detail) { case SWT.TRAVERSE_ESCAPE: // Do nothing in this case disposeTextWidget(); event.doit = true; event.detail = SWT.TRAVERSE_NONE; break; case SWT.TRAVERSE_RETURN: saveChangesAndDispose(obj); event.doit = true; event.detail = SWT.TRAVERSE_NONE; break; } } }); textEditor.addFocusListener(new FocusAdapter() { @Override public void focusLost( FocusEvent fe ) { //saveChangesAndDispose(obj); } }); if (textActionHandler != null) textActionHandler.addText(textEditor); } Composite createEditorParent() { Tree tree = columnsViewer.getTree(); Composite result = new Composite(tree, SWT.NONE); // Now let's make sure the target eObject is selected TreeItem[] selectedItems = cachedSelection; // tree.getSelection(); if (selectedItems.length > 0) { treeEditor.horizontalAlignment = SWT.LEFT; treeEditor.grabHorizontal = true; treeEditor.setEditor(result, selectedItems[0]); } return result; } /** * Indicates if the text editor is currently active and not disposed. * * @return <code>true</code>if active; <code>false</code> otherwise. * @since 4.2 */ boolean isTextEditorActive() { return (this.textEditor != null); } /** * Close the text widget and reset the editorText field. */ void disposeTextWidget() { if (textActionHandler != null) textActionHandler.removeText(textEditor); if (textEditorParent != null) { textEditorParent.dispose(); textEditorParent = null; textEditor = null; treeEditor.setEditor(null, null); } } /** * Save the changes and dispose of the text widget. * * @param resource - the resource to move. */ void saveChangesAndDispose( Object obj ) { // Cache the resource to avoid selection loss since a selection of // another item can trigger this method final String newName = textEditor.getText(); if( obj instanceof ColumnInfo) { ((ColumnInfo)obj).setName(newName); } else if( obj instanceof IWsdlAttributeInfo) { ((AttributeInfo)obj).setAlias(newName); } Runnable query = new Runnable() { @Override public void run() { // Dispose the text widget regardless disposeTextWidget(); notifyColumnDataChanged(); } }; this.columnsViewer.getTree().getShell().getDisplay().asyncExec(query); } }