/* * 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.ui.editors; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.core.runtime.SafeRunner; import org.eclipse.jface.util.SafeRunnable; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; /** * ModelEditorSelectionProvider is responsible for acting as the selection provider for the ModelEditor multi-page editor. It does * so by always registering as a SelectionChangeListener with the current ModelEditorPage's model object SelectionProvider. When * the currently active ModelEditorPage calls selectionChanged, that selection event is broadcast to whatever listeners have * registered with this object via the ISelectionProvider interface. * * @since 8.0 */ public class ModelEditorSelectionProvider implements ISelectionProvider { private ModelEditor modelEditor; private ArrayList listeners = new ArrayList(); private ISelection selection; ModelEditorPage sourcePage; /** * SelectionChangedListener to hook to the current ModelEditorPage */ private ISelectionChangedListener theSelectionChangedListener = new ISelectionChangedListener() { /** Called by the ModelEditorPage to signal a selection change */ @Override public void selectionChanged( SelectionChangedEvent e ) { if (isVisible(sourcePage)) { // save the current selection state and broadcast to all listeners setSelection(e.getSelection()); } } }; /** * Creates a selection provider for the given multi-page editor. * * @param multiPageEditor the multi-page editor */ public ModelEditorSelectionProvider( ModelEditor editor ) { this.modelEditor = editor; } /** * Controls whether or not this SelectionProvider should fire SelectionChangedEvents to listeners * * @enable true if this provider should fire events, false if events should be consumed. */ void setChangeEventsEnabled( boolean enable ) { } /** * Set the current ModelEditorPage being displayed in the ModelEditor. This object responds by obtaining the ModelEditorPage's * SelectionProvider and hooking it up suchthat selection changes are fired to any listeners. * * @param sourcePage */ public void setSourcePage( ModelEditorPage sourcePage ) { this.sourcePage = sourcePage; if (this.sourcePage != null) { ISelectionProvider sourceProvider = sourcePage.getModelObjectSelectionProvider(); if (sourceProvider != null) { sourceProvider.addSelectionChangedListener(theSelectionChangedListener); } } } public ModelEditorPage getSourcePage() { return sourcePage; } @Override public void addSelectionChangedListener( ISelectionChangedListener listener ) { synchronized (listeners) { if (!listeners.contains(listener)) { listeners.add(listener); } } } /** * Return the current selection. If the active editor has a selection provider, return it's selection. Otherwise, return the * last selection that came through this object. */ @Override public ISelection getSelection() { if (sourcePage != null && isVisible(sourcePage)) { ISelectionProvider selectionProvider = sourcePage.getModelObjectSelectionProvider(); if (selectionProvider != null) { return selectionProvider.getSelection(); } } return selection; } @Override public void removeSelectionChangedListener( ISelectionChangedListener listener ) { synchronized (listeners) { listeners.remove(listener); } } /** * Called when events come in from the ModelEditorPage and need to get broadcast out to other Viewers. */ @Override public synchronized void setSelection( ISelection selection ) { this.selection = selection; // if the modelEditor is not the active part, then the selection originated outside the editor // and should be fired to the selection service. Otherwise, it should be consumed. if (isActivePart()) { fireSelectionChanged(new SelectionChangedEvent(this, selection)); } } public boolean isVisible( ModelEditorPage page ) { return modelEditor.getCurrentPage() == page; } /** * Notifies all registered selection changed listeners that the editor's selection has changed. Only listeners registered at * the time this method is called are notified. * * @param event the selection changed event */ public void fireSelectionChanged( final SelectionChangedEvent event ) { // Defect 20052 Concurrent Modification problem // FIX = Copy the list before operating on it. Remove synchronize call. List copiedList = new ArrayList(listeners); final Iterator iter = copiedList.iterator(); while (iter.hasNext()) { final ISelectionChangedListener l = (ISelectionChangedListener)iter.next(); SafeRunner.run(new SafeRunnable() { @Override public void run() { l.selectionChanged(event); } @Override public void handleException( Throwable e ) { super.handleException(e); // If an unexpected exception happens, remove it // to make sure the workbench keeps running. // use the iterator-safe remove to prevent ConcurrentModEx: iter.remove(); } }); } } /** * Determine if this object's model editor is the active part in the workbench, indicating that the current selection event * came from it. * * @return true if this object's ModelEditor is the active part in the workbench. */ private boolean isActivePart() { return modelEditor.getEditorSite().getWorkbenchWindow().getPartService().getActivePart() == modelEditor; } }