/******************************************************************************* * Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is made available under the terms of the * Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Exadel, Inc. and Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.common.model.ui.attribute.editor; import java.beans.PropertyChangeEvent; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; import org.eclipse.jdt.internal.ui.JavaPluginImages; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.jboss.tools.common.meta.XAttribute; import org.jboss.tools.common.model.XModel; import org.jboss.tools.common.model.XModelObject; import org.jboss.tools.common.model.ui.IValueChangeListener; import org.jboss.tools.common.model.ui.IValueEditor; import org.jboss.tools.common.model.ui.IValueProvider; import org.jboss.tools.common.model.ui.ModelUIPlugin; import org.jboss.tools.common.model.ui.attribute.IPropertyDescriptorEx; import org.jboss.tools.common.model.ui.attribute.adapter.DefaultValueAdapter; import org.jboss.tools.common.model.ui.attribute.adapter.IModelPropertyEditorAdapter; import org.jboss.tools.common.model.ui.widgets.IWidgetSettings; import org.jboss.tools.common.model.util.AccessibleClasses; import org.jboss.tools.common.model.util.AccessibleJava; import org.jboss.tools.common.model.util.ISimpleTree; import org.jboss.tools.common.model.util.ModelFeatureFactory; import org.jboss.tools.common.model.util.ModelImages; public class JavaChoicerFieldEditor extends ExtendedFieldEditor implements IFieldEditor, IPropertyFieldEditor, IValueEditor, ModifyListener, ISelectionChangedListener { protected IPropertyEditor propertyEditor; protected IValueChangeListener valueChangeListener; protected IValueProvider valueProvider; protected IPropertyDescriptorEx description; private TreeViewer tree; private Text text; private String stringValue; private Composite treeAndText; private XModel model; private JavaElement rootElement = new JavaRootElement("Java"); //$NON-NLS-1$ AccessibleJava.IContextPackageProvider cpp = null; private static final String ROOT_PATH = "%root%"; //$NON-NLS-1$ private static final String EMPTY_PATH = ""; //$NON-NLS-1$ private static final Image ROOT_IMAGE = ModelImages.getImage("images/navigationtree/java.gif"); //$NON-NLS-1$ private static final Image PACKAGE_IMAGE = JavaPluginImages.get(JavaPluginImages.IMG_OBJS_PACKAGE); private static final Image CLASS_IMAGE = JavaPluginImages.get(JavaPluginImages.IMG_OBJS_CLASS); public JavaChoicerFieldEditor() {} public JavaChoicerFieldEditor(IWidgetSettings settings) { super(settings); } public JavaChoicerFieldEditor(String name, String labelText, Composite parent) { init(name, labelText); createControl(parent); } protected void adjustForNumColumns(int numColumns) { Control control = getLabelComposite(); ((GridData)control.getLayoutData()).horizontalSpan = numColumns; ((GridData)treeAndText.getLayoutData()).horizontalSpan = numColumns - 1; } protected void doFillIntoGrid(Composite parent, int numColumns) { /* Control control = createTabbedPane(parent); GridData gd = new GridData(GridData.FILL_BOTH); gd.horizontalSpan = numColumns; //gd.horizontalAlignment = GridData.HORIZONTAL_ALIGN_BEGINNING; gd.verticalAlignment = GridData.GRAB_VERTICAL; control.setLayoutData(gd); */ Control control = getLabelComposite(parent); GridData gd = new GridData(); gd.horizontalSpan = numColumns; //gd.horizontalAlignment = GridData.HORIZONTAL_ALIGN_BEGINNING; gd.verticalAlignment = GridData.GRAB_VERTICAL; control.setLayoutData(gd); treeAndText = getTreeAndTextControl(parent); gd = new GridData(GridData.FILL_BOTH); //gd.verticalAlignment = GridData.FILL; gd.horizontalSpan = numColumns; //gd.horizontalSpan = numColumns - 1; gd.grabExcessHorizontalSpace = true; treeAndText.setLayoutData(gd); } protected void doLoad() { } protected void doLoadDefault() { } protected void doStore() { } public int getNumberOfControls() { return 2; } protected Control createFavoritesChooser(Composite parent) { return getTreeAndTextControl(parent); } protected Composite getTreeAndTextControl(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(1, false); composite.setLayout(layout); layout.horizontalSpacing = 7; layout.verticalSpacing = 7; layout.marginHeight = 10; layout.marginWidth = 10; GridData gd; Label label; label = new Label(composite, SWT.NONE); label.setText(EditorMessages.getString("JavaChoicerFieldEditor.Tab1.Tree.Label")); //$NON-NLS-1$ tree = new TreeViewer(composite,SWT.BORDER | SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL); gd = new GridData(GridData.FILL_BOTH); //gd.verticalAlignment = GridData.FILL_VERTICAL; tree.getControl().setLayoutData(gd); tree.setContentProvider(new ContentProviderEx()); tree.setLabelProvider(new LabelProviderEx()); tree.setInput("Java"); //$NON-NLS-1$ if ((this.stringValue!=null)&&(this.stringValue.length()>0)) { ISelection selection = getSelection(this.stringValue); tree.setSelection(selection); } tree.addSelectionChangedListener(this); tree.setAutoExpandLevel(2); tree.getControl().addMouseListener(new MouseAdapter() { public void mouseDoubleClick(MouseEvent e) { if(getOwnerDialog() != null) { getOwnerDialog().okPressed(); } } }); label = new Label(composite, SWT.NONE); label.setText(EditorMessages.getString("JavaChoicerFieldEditor.Tab1.Text.Label")); //$NON-NLS-1$ text = new Text(composite,SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY); gd = new GridData(GridData.FILL_HORIZONTAL); text.setLayoutData(gd); text.setText(valueProvider.getStringValue(true)); text.setSelection(valueProvider.getStringValue(true).length()); text.addModifyListener(this); text.setFocus(); return composite; } private Object getObject(String path) { StringTokenizer st = new StringTokenizer(path, "."); //$NON-NLS-1$ JavaElement element = rootElement; String find = ""; //$NON-NLS-1$ while (st.hasMoreTokens()) { find = st.nextToken(); find = (element.getPath().equals(rootElement.getPath()))?find:element.getPath()+"."+find; //$NON-NLS-1$ if (element.getChildByPath(find) == null) { // try find like element startWith() int childCount = element.getChildCount(); for (int i = 0; i < childCount; ++i) { if (element.getChildAt(i).getPath().startsWith(find)) { return element.getChildAt(i); } } return null;//new StructuredSelection(new Object[] {element}); } element = element.getChildByPath(find); } return element; } private ISelection getSelection(String path) { Object o = getObject(path); if(o == null && cpp != null && path != null && path.length() > 0 && path.indexOf('.') < 0) { String pkg = cpp.getContextPackage(); if(pkg != null && pkg.length() > 0) { o = getObject(pkg + "." + path); //$NON-NLS-1$ } } return new StructuredSelection(new Object[] {o}); } protected String oldValue = null; protected void valueChanged(String newValue) { if ((newValue != null) && (!newValue.equals(oldValue))) { text.removeModifyListener(this); if ((text.getText()!=null)&&(!text.getText().equals(newValue))) { text.setText(newValue); text.setSelection(newValue.length()); } PropertyChangeEvent event = new PropertyChangeEvent(this, IPropertyEditor.VALUE, oldValue, newValue); valueChangeListener.valueChange(event); oldValue = newValue; this.stringValue = newValue; text.addModifyListener(this); } } protected void handleMouseUp(MouseEvent e) { } ISimpleTree list = null; class ContentProviderEx implements ITreeContentProvider { public ContentProviderEx() { /// if(model == null) throw new RuntimeException("Model is not provided for java class chooser."); list = new AccessibleClasses(model, true); } public Object[] getChildren(Object parentElement) { return ((JavaElement)parentElement).getChildrens(); } public Object getParent(Object element) { if (element instanceof JavaElement) { return ((JavaElement)element).getParent(); } else { return null; } } public boolean hasChildren(Object element) { return ((JavaElement)element).getChildCount()>0; } public Object[] getElements(Object inputElement) { rootElement.check(); return rootElement.getChildrens(); } public void dispose() { list = null; } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } } class LabelProviderEx extends LabelProvider { public Image getImage(Object element) { JavaElement javaElement = (JavaElement)element; if (ROOT_PATH.equals(javaElement.getPath())) { return ROOT_IMAGE; } else if (javaElement.isPackage()) { return PACKAGE_IMAGE; } else { return CLASS_IMAGE; } } public String getText(Object element) { return super.getText(element); } } class JavaRootElement extends JavaElement { public JavaRootElement(String name) { path = ROOT_PATH; this.name = name; } protected String _getPath() { return null; } } class JavaElement { protected JavaElement parent = null; private boolean isLoaded = false; protected String path = ""; //$NON-NLS-1$ protected String name = ""; //$NON-NLS-1$ protected boolean isPackage = false; private List<JavaElement> children = new ArrayList<JavaElement>(); protected JavaElement() { } public JavaElement(String parentpath, String name) { this.path = (parentpath == null) ? name : parentpath + "." + name; //$NON-NLS-1$ this.name = name; } public boolean isPackage() { return isPackage; } public JavaElement createChild(String name) { JavaElement c = new JavaElement(_getPath(), name); c.parent = this; return c; } public Object[] getChildrens() { return children.toArray(new Object[children.size()]); } public String getPath() { return path; } protected String _getPath() { return path; } public JavaElement getChildByPath(String path) { check(); JavaElement element; for (int i = 0; i < children.size(); ++i) { element = children.get(i); if (element.getPath().equals(path)) { return element; } } return null; } protected void check() { if(isLoaded) return; isLoaded = true; String[] ns = list.getContent(path); if(ns == null) return; for (int i = 0; i < ns.length; i++) { String s = ns[i]; boolean p = s.endsWith("."); //$NON-NLS-1$ if(p) s = s.substring(0, s.length() - 1); if(!isJavaName(s)) continue; JavaElement c = createChild(s); c.isPackage = p; children.add(c); } } boolean isJavaName(String name) { if(name.length() == 0) return false; if(!Character.isJavaIdentifierStart(name.charAt(0))) return false; for (int i = 1; i < name.length(); i++) { if(!Character.isJavaIdentifierPart(name.charAt(i))) return false; } return true; } public JavaElement getChildAt(int childIndex) { check(); return children.get(childIndex); } public int getChildCount() { check(); return children.size(); } public JavaElement getParent() { return parent; } public int getIndex(JavaElement node) { check(); for (int i = 0; i < children.size(); i++) if(children.get(i) == node) return i; return -1; } public boolean getAllowsChildren() { return true; } public boolean isLeaf() { check(); return getChildCount() == 0; } public Iterator<JavaElement> children() { return children.iterator(); } public String toString() { return name; } } // IValueEditor public void setValueChangeListener(IValueChangeListener valueChangeListener) { this.valueChangeListener = valueChangeListener; } public void setValueProvider(IValueProvider valueProvider) { this.valueProvider = valueProvider; } // ModifyListener public void modifyText(ModifyEvent e) { String newValue = ((Text)e.getSource()).getText(); tree.removeSelectionChangedListener(this); if (newValue.endsWith(" ")) { //$NON-NLS-1$ StructuredSelection selection = (StructuredSelection)tree.getSelection(); JavaElement element = (JavaElement)selection.getFirstElement(); if (element != null) { if (!ROOT_PATH.equals(element.getPath())) { valueChanged(element.getPath()); } else { valueChanged(EMPTY_PATH); } newValue = stringValue; if(newValue == null) newValue = ""; //$NON-NLS-1$ text.setText(newValue); text.setSelection(newValue.length()); } } else { valueChanged(newValue.trim()); } tree.setSelection(getSelection(((Text)e.getSource()).getText())); Object currentObject = getObject(((Text)e.getSource()).getText()); if (currentObject!=null) { tree.expandToLevel(currentObject,1); } tree.addSelectionChangedListener(this); } protected void init() { this.stringValue = valueProvider.getStringValue(true); //setPropertyChangeListener(this); } public void setEnabled(boolean enabled){ // TODO; super.setEnabled(enabled); } // IPropertyFieldEditor public void setPropertyEditor(IPropertyEditor propertyEditor) { this.propertyEditor = propertyEditor; if (propertyEditor!=null) { valueProvider = (IValueProvider)propertyEditor.getAdapter(IValueProvider.class); valueChangeListener = (IValueChangeListener)propertyEditor.getAdapter(IValueChangeListener.class); Object input = propertyEditor.getInput(); if(input instanceof DefaultValueAdapter) { model = ((DefaultValueAdapter)input).getModel(); XModelObject xmo = ((DefaultValueAdapter)valueProvider).getModelObject(); XAttribute attr = ((DefaultValueAdapter)valueProvider).getAttribute(); if (attr!=null) { AccessibleJava.IContextPackageProvider cpp = getPackageProvider(); if(cpp != null) { this.cpp = cpp; cpp.setObject(xmo); } } } } init(); } // IFieldEditor public Control[] getControls(Composite parent) { return new Control[] {getTreeAndTextControl(parent)}; //return new Control[] {createTabbedPane(parent)}; } public void selectionChanged(SelectionChangedEvent event) { StructuredSelection selection = (StructuredSelection)event.getSelection(); JavaElement element = selection.isEmpty() ? null : (JavaElement)selection.getFirstElement(); if (element != null && !ROOT_PATH.equals(element.getPath())) { valueChanged(element.getPath()); } else { valueChanged(EMPTY_PATH); } } public void cut() { } public void copy() { } public void paste() { } public void delete() { } private AccessibleJava.IContextPackageProvider getPackageProvider() { IModelPropertyEditorAdapter adapter = (IModelPropertyEditorAdapter)propertyEditor.getInput(); XAttribute a = adapter.getAttribute(); if(a == null) return null; String cls = a.getProperty("contextPackageProvider"); //$NON-NLS-1$ if(cls == null || cls.length() == 0) return null; try { AccessibleJava.IContextPackageProvider o = (AccessibleJava.IContextPackageProvider)ModelFeatureFactory.getInstance().createFeatureInstance(cls); if(o != null) o.setObject(((DefaultValueAdapter)adapter).getModelObject()); return o; } catch (ClassCastException e) { ModelUIPlugin.getPluginLog().logError(e); } return null; } }