com.architexa.org.eclipse.gef.ui.parts.SelectionSynchronizer.java Source code

Java tutorial

Introduction

Here is the source code for com.architexa.org.eclipse.gef.ui.parts.SelectionSynchronizer.java

Source

/*******************************************************************************
 * Copyright (c) 2000, 2005 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 com.architexa.org.eclipse.gef.ui.parts;

import com.architexa.org.eclipse.gef.EditPart;
import com.architexa.org.eclipse.gef.EditPartViewer;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

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;

/**
 * A utility for synchronizing the selection of multiple EditPartViewers.  This class
 * performs selection synchronization by taking the selection from one viewer, and mapping
 * it to the selection in another viewer.  The mapping is performed by matching the models
 * of the selected EditParts from one viewer to the EditParts with the same models in
 * another. The can be customized by overriding the {@link #convert(EditPartViewer,
 * EditPart)} method.
 * @author hudsonr
 */
public class SelectionSynchronizer implements ISelectionChangedListener {

    private List viewers = new ArrayList();
    private boolean isDispatching = false;
    private int disabled = 0;
    private EditPartViewer pendingSelection;

    /**
     * Adds a viewer to the set of synchronized viewers
     * @param viewer the viewer
     */
    public void addViewer(EditPartViewer viewer) {
        viewer.addSelectionChangedListener(this);
        viewers.add(viewer);
    }

    /**
     * Maps the given editpart from one viewer to an editpart in another viewer. It returns
     * <code>null</code> if there is no corresponding part. This method can be overridden
     * to provide custom mapping.
     * @param viewer the viewer being mapped to
     * @param part a part from another viewer
     * @return <code>null</code> or a corresponding editpart
     */
    protected EditPart convert(EditPartViewer viewer, EditPart part) {
        Object temp = viewer.getEditPartRegistry().get(part.getModel());
        EditPart newPart = null;
        if (temp != null) {
            newPart = (EditPart) temp;
        }
        return newPart;
    }

    /**
     * Removes the viewer from the set of synchronized viewers
     * @param viewer the viewer to remove
     */
    public void removeViewer(EditPartViewer viewer) {
        viewer.removeSelectionChangedListener(this);
        viewers.remove(viewer);
        if (pendingSelection == viewer)
            pendingSelection = null;
    }

    /**
     * Receives notification from one viewer, and maps selection to all other members.
     * @param event the selection event
     */
    public void selectionChanged(SelectionChangedEvent event) {
        if (isDispatching)
            return;
        EditPartViewer source = (EditPartViewer) event.getSelectionProvider();
        if (disabled > 0) {
            pendingSelection = source;
        } else {
            ISelection selection = event.getSelection();
            syncSelection(source, selection);
        }
    }

    private void syncSelection(EditPartViewer source, ISelection selection) {
        isDispatching = true;
        for (int i = 0; i < viewers.size(); i++) {
            if (viewers.get(i) != source) {
                EditPartViewer viewer = (EditPartViewer) viewers.get(i);
                setViewerSelection(viewer, selection);
            }
        }
        isDispatching = false;
    }

    /**
     * Enables or disabled synchronization between viewers.
     * @since 3.1
     * @param value <code>true</code> if synchronization should occur
     */
    public void setEnabled(boolean value) {
        if (!value)
            disabled++;
        else if (--disabled == 0 && pendingSelection != null) {
            syncSelection(pendingSelection, pendingSelection.getSelection());
            pendingSelection = null;
        }
    }

    private void setViewerSelection(EditPartViewer viewer, ISelection selection) {
        ArrayList result = new ArrayList();
        Iterator iter = ((IStructuredSelection) selection).iterator();
        while (iter.hasNext()) {
            EditPart part = convert(viewer, (EditPart) iter.next());
            if (part != null)
                result.add(part);
        }
        viewer.setSelection(new StructuredSelection(result));
        if (result.size() > 0)
            viewer.reveal((EditPart) result.get(result.size() - 1));
    }

}