com.nokia.sdt.uidesigner.ui.SelectionManager.java Source code

Java tutorial

Introduction

Here is the source code for com.nokia.sdt.uidesigner.ui.SelectionManager.java

Source

/*
* Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: 
*
*/

package com.nokia.sdt.uidesigner.ui;

import com.nokia.sdt.datamodel.adapter.IComponentInstance;
import com.nokia.sdt.editor.*;
import com.nokia.sdt.uidesigner.ui.editparts.*;
import com.nokia.sdt.uidesigner.ui.utils.Adapters;
import com.nokia.sdt.uidesigner.ui.utils.EditorUtils;
import com.nokia.cpp.internal.api.utils.core.Logging;

import org.eclipse.core.runtime.*;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.gef.*;
import org.eclipse.jface.viewers.*;
import org.eclipse.ui.*;

import java.util.*;

/**
 * SelectionManager
 * 
 * <li>A selection provider that will unify the selections of both
 * GraphicalViewers so as to provide a single selection from the EditorPart.
 * <li>Also, a SelectionSynchronizer implementation that allows selection
 * setting from other sources besides viewers.
 * <li>Handles left over selections from editor reload operation.
 */
public class SelectionManager implements ISelectionManager {

    private IDesignerEditor editor;
    private ListenerList selectionChangedListeners = new ListenerList(ListenerList.IDENTITY);
    private IPartService partService;
    private IPartListener partListener;
    private List leftoverSelectedNames;
    private Set savedComponentEditors = new HashSet();
    private List partsWithVisibleScrollbars = new ArrayList();
    private ISelection currentSelection;

    private List viewers = new ArrayList();
    private boolean isDispatching;

    class PartListener implements IPartListener {

        private IDesignerEditor editor;

        public PartListener(IDesignerEditor editor) {
            this.editor = editor;
        }

        public void partActivated(IWorkbenchPart part) {
            if (part.equals(editor.getAdapter(IWorkbenchPart.class))) {
                if (leftoverSelectedNames != null) {
                    setSelectionFromNames(leftoverSelectedNames);
                    leftoverSelectedNames = null;
                }
            }
        }

        public void partBroughtToTop(IWorkbenchPart part) {
        }

        public void partClosed(IWorkbenchPart part) {
        }

        public void partDeactivated(IWorkbenchPart part) {
        }

        public void partOpened(IWorkbenchPart part) {
            if (!part.equals(editor))
                return;

            getLeftoverSelectedNames();
        }

    }

    public SelectionManager(IDesignerEditor editor, IPartService partService) {
        this.editor = editor;
        this.partService = partService;
        partListener = new PartListener(editor);
        partService.addPartListener(partListener);
    }

    public void dispose() {
        partService.removePartListener(partListener);
        editor = null;
        selectionChangedListeners.clear();
        viewers.clear();
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.viewers.ISelectionProvider#addSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
     */
    public void addSelectionChangedListener(ISelectionChangedListener listener) {
        selectionChangedListeners.add(listener);
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.viewers.ISelectionProvider#removeSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
     */
    public void removeSelectionChangedListener(ISelectionChangedListener listener) {
        selectionChangedListeners.remove(listener);
    }

    private boolean editPartListContainsModel(List<EditPart> editPartList, Object model) {
        for (EditPart editPart : editPartList) {
            if (editPart.getModel().equals(model))
                return true;
        }

        return false;
    }

    private void addUniqueSelectedPartsFromViewer(List<EditPart> selectedEditParts, EditPartViewer viewer) {
        if (viewer != null) {
            for (EditPart editPart : getPrunedEditParts(viewer.getSelectedEditParts())) {
                if (!editPartListContainsModel(selectedEditParts, editPart.getModel())) {
                    selectedEditParts.add(editPart);
                }
            }
        }
    }

    private void addModelsFromViewer(Collection<EObject> selectedObjects, EditPartViewer viewer) {
        if (viewer != null) {
            for (EditPart editPart : getPrunedEditParts(viewer.getSelectedEditParts())) {
                selectedObjects.add((EObject) editPart.getModel());
            }
        }
    }

    private boolean containsLayoutObjects(Collection<EObject> selectedObjects) {
        for (EObject object : selectedObjects) {
            if (Adapters.getLayoutObject(object) != null && EditorUtils.findTransientObject(object) == null)
                return true;
        }
        return false;
    }

    private boolean containsOutlineOnlyObjects(Collection<EObject> selectedObjects) {
        for (EObject object : selectedObjects) {
            if (Adapters.getLayoutObject(object) == null && !EditorUtils.isNonLayoutObject(object, null))
                return true;
        }
        return false;
    }

    private Collection<EditPart> getPrunedEditParts(Collection<EditPart> parts) {
        // we remove content parts because they are not actual model objects
        // also remove the transient edit parts, so the selection will contain the non-layout part
        List<EditPart> prunedParts = new ArrayList<EditPart>();
        for (EditPart editPart : parts) {
            if (editPart.getModel() != null && !editPart.getModel().equals(editor.getModelObject())
                    && !(editPart instanceof TransientObjectEditPart))
                prunedParts.add(editPart);
        }

        return prunedParts;
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.viewers.ISelectionProvider#getSelection()
     */
    public ISelection getSelection() {
        if (currentSelection != null)
            return currentSelection;

        // create a new list of edit parts from the various viewers.
        // favor upper viewer parts to outline part to allow alignment and matching actions to work.
        // However, avoid mixing outline with graphical parts - some GEF actions throw NPEs.
        // So if there are outline-only objects in the selection, use only outline parts
        List<EditPart> selectedEditParts = new ArrayList();
        boolean useGraphicalViewers = false;
        EditPartViewer outlineViewer = this.editor.getOutlineViewer();
        if (outlineViewer != null) {
            Set<EObject> selectedObjects = new HashSet();
            addModelsFromViewer(selectedObjects, outlineViewer);
            if (selectedObjects.isEmpty())
                return currentSelection = StructuredSelection.EMPTY;

            if (containsOutlineOnlyObjects(selectedObjects))
                addUniqueSelectedPartsFromViewer(selectedEditParts, outlineViewer);
            else
                useGraphicalViewers = true;
        } else
            useGraphicalViewers = true;

        if (useGraphicalViewers) {
            addUniqueSelectedPartsFromViewer(selectedEditParts, this.editor.getUpperGraphicalViewer());
            addUniqueSelectedPartsFromViewer(selectedEditParts, this.editor.getLowerGraphicalViewer());
        }

        // prune the list to not include contents or transient parts 
        List selection = new ArrayList();
        for (EditPart editPart : selectedEditParts) {
            selection.add(editPart);
        }

        return currentSelection = new StructuredSelection(selection);
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.viewers.ISelectionProvider#setSelection(org.eclipse.jface.viewers.ISelection)
     */
    public void setSelection(ISelection newSelection) {
        syncSelection(null, newSelection);
    }

    public void addViewer(EditPartViewer viewer) {
        viewer.addSelectionChangedListener(this);
        viewers.add(viewer);
    }

    public void removeViewer(EditPartViewer viewer) {
        viewer.removeSelectionChangedListener(this);
        viewers.remove(viewer);
    }

    protected EditPart getViewerEditPart(EditPartViewer viewer, Object model) {
        if (model == null)
            return null;
        Object temp = viewer.getEditPartRegistry().get(model);
        EditPart newPart = null;
        if (temp != null) {
            newPart = (EditPart) temp;
        }
        return newPart;
    }

    private void syncSelection(EditPartViewer source, ISelection selection) {
        if (editor.getUpperGraphicalViewer() == null)
            return;

        determineTransientMode(selection);
        adviseEditors(selection);
        resetContainerScrollbarsVisibility(selection);
        isDispatching = true;
        if (source instanceof org.eclipse.gef.ui.parts.TreeViewer) {
            // tree viewer => all others
            EditorUtils.setDisplayModelSelectedObjects(editor.getDisplayModel(),
                    getModelObjectsFromSelection(selection));
            setViewerSelection(editor.getUpperGraphicalViewer(), selection);
            setViewerSelection(editor.getLowerGraphicalViewer(), selection);
        } else if (editor.getUpperGraphicalViewer().equals(source)) {
            // if upper, sel => tree; null => lower
            setViewerSelection(editor.getOutlineViewer(), selection);
            setViewerSelection(editor.getLowerGraphicalViewer(), selection);
        } else if ((source != null) && source.equals(editor.getLowerGraphicalViewer())) {
            // if lower, sel => tree; null => upper
            setViewerSelection(editor.getOutlineViewer(), selection);
            setViewerSelection(editor.getUpperGraphicalViewer(), selection);
        } else if (source == null) {
            // if null source, set all
            setViewerSelection(editor.getUpperGraphicalViewer(), selection);
            setViewerSelection(editor.getLowerGraphicalViewer(), selection);
            setViewerSelection(editor.getOutlineViewer(), selection);
        }
        isDispatching = false;

        if (source != null)
            revealSelectionInViewer(source, selection);

        // tell the rest of the world
        fireSelectionChanged(getSelection());
    }

    private List getViewerSelection(EditPartViewer viewer, ISelection selection) {
        if ((viewer == null) || (viewer.getControl() == null))
            return null;

        ArrayList result = new ArrayList();
        for (Iterator iter = ((IStructuredSelection) selection).iterator(); iter.hasNext();) {
            EditPart part = getViewerEditPart(viewer, getObjectFromSelected(iter.next()));
            if (part != null)
                result.add(part);
        }

        return result;
    }

    private void setViewerSelection(EditPartViewer viewer, ISelection selection) {
        if (viewer == null)
            return;
        List selectedParts = getViewerSelection(viewer, selection);
        if ((selectedParts != null) && (!selectedParts.isEmpty())) {
            viewer.setSelection(new StructuredSelection(selectedParts));
            if (selectedParts.size() > 0) {
                viewer.reveal((EditPart) selectedParts.get(selectedParts.size() - 1));
            }
        } else {
            viewer.setSelection(StructuredSelection.EMPTY);
        }
    }

    public void revealSelectionInViewer(EditPartViewer viewer, ISelection selection) {
        List selectedParts = getViewerSelection(viewer, selection);
        if ((selectedParts != null) && (!selectedParts.isEmpty())) {
            if (selectedParts.size() > 0) {
                for (Iterator<EditPart> iter = selectedParts.iterator(); iter.hasNext();) {
                    EditPart part = iter.next();
                    if (part.getModel() instanceof EObject) {
                        viewer.reveal(part);
                        break;
                    }
                }
            }
        }
    }

    public void selectionChanged(SelectionChangedEvent event) {
        currentSelection = null;
        if (isDispatching)
            return;

        // this synchronizes between viewers
        EditPartViewer source = (EditPartViewer) event.getSelectionProvider();
        ISelection selection = event.getSelection();
        syncSelection(source, selection);
    }

    private void determineTransientMode(ISelection selection) {
        List selectedObjects = getModelObjectsFromSelection(selection);

        if (selectedObjects.isEmpty() || containsLayoutObjects(selectedObjects))
            editor.setLayoutMode();

        // if all objects belong to the same transient root, set to transient, else set to layout
        // set to transient mode, else set to layout mode
        EObject transientRoot = null;
        boolean makeTransient = false;
        for (Iterator iter = selectedObjects.iterator(); iter.hasNext();) {
            EObject object = (EObject) iter.next();
            if (transientRoot == null) {
                transientRoot = EditorUtils.findTransientObject(object);
            }
            makeTransient = EditorUtils.isSameObjectOrChild(transientRoot, object);
        }

        if (makeTransient) {
            Object prevRoot = editor.getTransientRootObject();
            if ((prevRoot != null) && !transientRoot.equals(prevRoot))
                editor.setLayoutMode();

            editor.setTransientMode(transientRoot);
        } else
            editor.setLayoutMode();
    }

    private List getModelObjectsFromSelection(ISelection selection) {
        List selectedObjects = new ArrayList();
        for (Iterator iter = ((StructuredSelection) selection).toList().iterator(); iter.hasNext();) {
            EObject object = getObjectFromSelected(iter.next());
            if (object != null)
                selectedObjects.add(object);
        }
        return selectedObjects;
    }

    private void adviseEditors(ISelection selection) {
        Set newComponentEditors = new HashSet();

        // add new editors from selection
        for (Iterator iter = ((StructuredSelection) selection).iterator(); iter.hasNext();) {
            EObject object = getObjectFromSelected(iter.next());
            if (object != null) {
                IComponentEditor componentEditor = Adapters.getComponentEditor(object);
                if (componentEditor != null)
                    newComponentEditors.add(componentEditor);
            }
        }

        // advise saved editors that are not in the new set to exit edit mode
        for (Iterator iter = savedComponentEditors.iterator(); iter.hasNext();) {
            IComponentEditor componentEditor = (IComponentEditor) iter.next();
            if (!newComponentEditors.contains(componentEditor))
                componentEditor.endEditing();
        }

        // advise new component editors that are not in the saved set to enter edit mode
        for (Iterator iter = newComponentEditors.iterator(); iter.hasNext();) {
            IComponentEditor componentEditor = (IComponentEditor) iter.next();
            if (!savedComponentEditors.contains(componentEditor))
                componentEditor.beginEditing(editor);
        }

        // replace the saved component editors with the new set
        savedComponentEditors = newComponentEditors;
    }

    private void setContainerScrollbarsVisible(EditPart selectedPart, boolean visible) {
        if (!(selectedPart instanceof ModelObjectEditPart))
            return;

        if (selectedPart instanceof LayoutContainerEditPart) {
            ((LayoutContainerEditPart) selectedPart).setScrollbarsVisible(visible);
            if (visible)
                partsWithVisibleScrollbars.add(selectedPart);
        }
        setContainerScrollbarsVisible(selectedPart.getParent(), visible);
    }

    private void resetContainerScrollbarsVisibility(ISelection selection) {
        for (Iterator iter = partsWithVisibleScrollbars.iterator(); iter.hasNext();) {
            EditPart part = (EditPart) iter.next();
            setContainerScrollbarsVisible(part, false);
        }

        partsWithVisibleScrollbars.clear();
        GraphicalViewer upperGraphicalViewer = editor.getUpperGraphicalViewer();
        for (Iterator iter = ((StructuredSelection) selection).iterator(); iter.hasNext();) {
            EObject object = getObjectFromSelected(iter.next());
            if (object != null) {
                EditPart part = getPart(upperGraphicalViewer, object);
                setContainerScrollbarsVisible(part, true);
            }
        }
    }

    private void fireSelectionChanged(ISelection selection) {
        Object[] listeners = selectionChangedListeners.getListeners();
        selection = getSelection();
        for (int i = 0; i < listeners.length; ++i) {
            ((ISelectionChangedListener) listeners[i]).selectionChanged(new SelectionChangedEvent(this, selection));
        }
    }

    private EditPart getPart(EditPartViewer viewer, Object object) {
        if (object == null)
            return null;

        Object temp = viewer.getEditPartRegistry().get(object);
        EditPart newPart = null;
        if (temp != null) {
            newPart = (EditPart) temp;
        }
        return newPart;
    }

    public void setSelectionFromNames(List objectNames) {
        List parts = new ArrayList();
        for (Iterator iter = objectNames.iterator(); iter.hasNext();) {
            EObject object = this.editor.getDataModel().findByNameProperty(iter.next().toString());
            EditPart part = getPart(this.editor.getUpperGraphicalViewer(), object);
            if (part != null)
                parts.add(part);
            else if (this.editor.getLowerGraphicalViewer() != null) {
                part = getPart(this.editor.getLowerGraphicalViewer(), object);
                if (part != null)
                    parts.add(part);

            }
        }
        setSelection(new StructuredSelection(parts));
    }

    public void getLeftoverSelectedNames() {
        try {
            IDesignerDataModelEditor ddme = (IDesignerDataModelEditor) editor
                    .getAdapter(IDesignerDataModelEditor.class);
            QualifiedName key = new QualifiedName(UIDesignerPlugin.getDefault().toString(), ddme.getPartName());
            leftoverSelectedNames = (List) editor.getDataModelResource().getSessionProperty(key);
            editor.getDataModelResource().setSessionProperty(key, null);
        } catch (CoreException e) {
            IStatus status = Logging.newStatus(UIDesignerPlugin.getDefault(), e);
            Logging.log(UIDesignerPlugin.getDefault(), status);
        }
    }

    public void reloadSelection() {
        getLeftoverSelectedNames();
        if (leftoverSelectedNames != null) {
            setSelectionFromNames(leftoverSelectedNames);
            leftoverSelectedNames = null;
        }
    }

    public List getSelectedModelNames() {
        ISelection sel = getSelection();
        if (!(sel instanceof IStructuredSelection))
            return null;

        List objectNames = new ArrayList();
        IStructuredSelection selection = (IStructuredSelection) sel;
        for (Iterator iter = selection.iterator(); iter.hasNext();) {
            EObject object = getObjectFromSelected(iter.next());
            if (object != null) {
                IComponentInstance instance = Adapters.getComponentInstance(object);
                objectNames.add(instance.getName());
            }
        }

        return objectNames;
    }

    public boolean isComponentEditing() {
        return !savedComponentEditors.isEmpty();
    }

    public void setSync(boolean sync) {
        isDispatching = !sync;
    }

    private EObject getObjectFromSelected(Object object) {
        if (object instanceof EditPart) {
            object = ((EditPart) object).getModel();
        }
        if (object instanceof EObject)
            return (EObject) object;

        return null;
    }
}