/******************************************************************************* * Copyright (c) 2001, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are 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: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.wst.xsd.ui.internal.adt.outline; import java.util.List; import java.util.Stack; import org.eclipse.emf.common.notify.Notifier; import org.eclipse.emf.common.notify.impl.AdapterImpl; import org.eclipse.jface.action.IStatusLineManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Menu; import org.eclipse.ui.part.MultiPageSelectionProvider; import org.eclipse.wst.xml.ui.internal.contentoutline.JFaceNodeLabelProvider; import org.eclipse.wst.xsd.ui.internal.adapters.CategoryAdapter; import org.eclipse.wst.xsd.ui.internal.adapters.RedefineCategoryAdapter; import org.eclipse.wst.xsd.ui.internal.adapters.XSDAttributeDeclarationAdapter; import org.eclipse.wst.xsd.ui.internal.adapters.XSDAttributeGroupDefinitionAdapter; import org.eclipse.wst.xsd.ui.internal.adapters.XSDComplexTypeDefinitionAdapter; import org.eclipse.wst.xsd.ui.internal.adapters.XSDElementDeclarationAdapter; import org.eclipse.wst.xsd.ui.internal.adapters.XSDModelGroupDefinitionAdapter; import org.eclipse.wst.xsd.ui.internal.adapters.XSDRedefineAdapter; import org.eclipse.wst.xsd.ui.internal.adapters.XSDSchemaAdapter; import org.eclipse.wst.xsd.ui.internal.adapters.XSDSchemaDirectiveAdapter; import org.eclipse.wst.xsd.ui.internal.adapters.XSDSimpleTypeDefinitionAdapter; import org.eclipse.wst.xsd.ui.internal.adt.design.DesignViewContextMenuProvider; import org.eclipse.wst.xsd.ui.internal.adt.design.editparts.model.IModelProxy; import org.eclipse.wst.xsd.ui.internal.adt.facade.IModel; import org.eclipse.xsd.XSDConcreteComponent; import org.eclipse.xsd.XSDSchema; public class ADTContentOutlinePage extends ExtensibleContentOutlinePage { protected int level = 0; protected MultiPageSelectionProvider selectionManager; protected SelectionManagerSelectionChangeListener selectionManagerSelectionChangeListener = new SelectionManagerSelectionChangeListener(); public ADTContentOutlinePage() { super(); } public void createControl(Composite parent) { super.createControl(parent); getTreeViewer().setContentProvider(contentProvider); getTreeViewer().setLabelProvider(labelProvider); getTreeViewer().setInput(model); getTreeViewer().addSelectionChangedListener(this); MenuManager menuManager = new MenuManager("#popup");//$NON-NLS-1$ menuManager.setRemoveAllWhenShown(true); Menu menu = menuManager.createContextMenu(getTreeViewer().getControl()); getTreeViewer().getControl().setMenu(menu); setSelectionManager(editor.getSelectionManager()); // Create menu...for now reuse graph's. Note edit part viewer = null DesignViewContextMenuProvider menuProvider = new DesignViewContextMenuProvider(editor, null, editor.getSelectionManager()); menuManager.addMenuListener(menuProvider); getSite().registerContextMenu("org.eclipse.wst.xsd.ui.popup.outline", menuManager, editor.getSelectionManager()); //$NON-NLS-1$ // enable popupMenus extension // getSite().registerContextMenu("org.eclipse.wst.xsdeditor.ui.popup.outline", // menuManager, xsdEditor.getSelectionManager()); // drill down from outline view getTreeViewer().getControl().addMouseListener(new MouseAdapter() { public void mouseDoubleClick(MouseEvent e) { ISelection iSelection = getTreeViewer().getSelection(); if (iSelection instanceof StructuredSelection) { StructuredSelection selection = (StructuredSelection) iSelection; Object obj = selection.getFirstElement(); if (obj instanceof XSDConcreteComponent) { XSDConcreteComponent comp = (XSDConcreteComponent) obj; if (comp.getContainer() instanceof XSDSchema) { // getXSDEditor().getGraphViewer().setInput(obj); } } } } }); } class XSDKeyListener extends KeyAdapter { } public void dispose() { contentProvider.dispose(); super.dispose(); } public void setExpandToLevel(int i) { level = i; } public void setInput(Object value) { getTreeViewer().setInput(value); getTreeViewer().expandToLevel(level); } // public ISelection getSelection() // { // if (getTreeViewer() == null) // return StructuredSelection.EMPTY; // return getTreeViewer().getSelection(); // } public void setSelectionManager(MultiPageSelectionProvider newSelectionManager) { // disconnect from old one if (selectionManager != null) { selectionManager.removeSelectionChangedListener(selectionManagerSelectionChangeListener); } selectionManager = newSelectionManager; // connect to new one if (selectionManager != null) { selectionManager.addSelectionChangedListener(selectionManagerSelectionChangeListener); } } protected class SelectionManagerSelectionChangeListener implements ISelectionChangedListener { public void selectionChanged(SelectionChangedEvent event) { updateStatusLine(getSite().getActionBars().getStatusLineManager(), event.getSelection()); if (event.getSelectionProvider() != ADTContentOutlinePage.this) //getTreeViewer()) { StructuredSelection selection = (StructuredSelection)event.getSelection(); StructuredSelection currentSelection = (StructuredSelection) getTreeViewer().getSelection(); Object selectionFirstElement = selection.getFirstElement(); Object currentFirstElement = currentSelection.getFirstElement(); // TODO: Hack to prevent losing a selection when the schema is selected in the // source. Fix is to prevent the source from firing off selection changes when // the selection source is not the source view. if (selectionFirstElement instanceof IModel) { if (!(currentFirstElement instanceof IModelProxy) || currentFirstElement instanceof RedefineCategoryAdapter) { getTreeViewer().setSelection(event.getSelection(), true); } } else if (selectionFirstElement instanceof XSDSchemaDirectiveAdapter) { if (!(currentFirstElement instanceof RedefineCategoryAdapter)) { getTreeViewer().setSelection(event.getSelection(), true); } } else { IStructuredSelection structuredSelection = (IStructuredSelection) event.getSelection(); List list = structuredSelection.toList(); int selectionLength = list.size(); if (selectionLength > 0) { for (int i = 0; i < selectionLength; i++) { Object item = list.get(i); if (item instanceof AdapterImpl) { Notifier target = ((AdapterImpl) item).getTarget(); if (!(target instanceof XSDConcreteComponent)) continue; XSDConcreteComponent xsdConcreteComponent = (XSDConcreteComponent) target; // need to expand parent before child, thus a stack is required Stack componentStack = new Stack(); while (xsdConcreteComponent != null) { componentStack.push(xsdConcreteComponent); xsdConcreteComponent = xsdConcreteComponent.getContainer(); } // At this point the stack must have the XSDSchemaAdapter and // at least one component if (componentStack.size() < 2) continue; // Pop off the top node, since it is the XSDSchemaAdapter, which // isn't // used as part of finding the outline view hierarchy componentStack.pop(); if (((XSDConcreteComponent) componentStack.peek()).eAdapters().size() <= 0) continue; Object object = ((XSDConcreteComponent) componentStack.peek()).eAdapters().get(0); // Find out which category the selected item is contained in int categoryIndex = -1; if (object instanceof XSDSchemaDirectiveAdapter) { categoryIndex = CategoryAdapter.DIRECTIVES; } else if (object instanceof XSDElementDeclarationAdapter) { categoryIndex = CategoryAdapter.ELEMENTS; } else if (object instanceof XSDAttributeDeclarationAdapter) { categoryIndex = CategoryAdapter.ATTRIBUTES; } else if (object instanceof XSDAttributeGroupDefinitionAdapter) { categoryIndex = CategoryAdapter.ATTRIBUTES; } else if (object instanceof XSDComplexTypeDefinitionAdapter || object instanceof XSDSimpleTypeDefinitionAdapter) { categoryIndex = CategoryAdapter.TYPES; } else if (object instanceof XSDModelGroupDefinitionAdapter) { categoryIndex = CategoryAdapter.GROUPS; } // Expand the category if (categoryIndex == -1) continue; CategoryAdapter category = ((XSDSchemaAdapter) model).getCategory(categoryIndex); treeViewer.setExpandedState(category, true); // Do not expand current node of interest, just its parents while (componentStack.size() > 1) { object = componentStack.pop(); if (object instanceof XSDConcreteComponent) { XSDConcreteComponent component = (XSDConcreteComponent) object; if (component.eAdapters().size() > 0) { // expand getTreeViewer().setExpandedState(component.eAdapters().get(0), true); } } } } } } // Bug 251474 - We will restrict selection to only one item if (selectionLength == 1) { getTreeViewer().setSelection(event.getSelection(), true); } else { if(structuredSelection.getFirstElement() !=null) getTreeViewer().setSelection(new StructuredSelection(structuredSelection.getFirstElement()), true); } } } } } protected void updateStatusLine(IStatusLineManager mgr, ISelection selection) { String text = null; Image image = null; ILabelProvider statusLineLabelProvider = new StatusLineLabelProvider(getTreeViewer()); if (statusLineLabelProvider != null && selection instanceof IStructuredSelection && !selection.isEmpty()) { Object firstElement = ((IStructuredSelection) selection).getFirstElement(); if (firstElement instanceof XSDRedefineAdapter) return; text = statusLineLabelProvider.getText(firstElement); image = statusLineLabelProvider.getImage(firstElement); } if (image == null) { mgr.setMessage(text); } else { mgr.setMessage(image, text); } } protected class StatusLineLabelProvider extends JFaceNodeLabelProvider { TreeViewer treeViewer = null; public StatusLineLabelProvider(TreeViewer viewer) { treeViewer = viewer; } public String getText(Object element) { if (element == null) return null; StringBuffer s = new StringBuffer(); s.append(labelProvider.getText(element)); return s.toString(); } public Image getImage(Object element) { return labelProvider.getImage(element); } } }