/**
 * This program and the accompanying materials
 * are made available under the terms of the License
 * which accompanies this distribution in the file LICENSE.txt
 */
package com.archimatetool.editor.views.tree;

import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PlatformUI;

import com.archimatetool.editor.diagram.IArchimateDiagramEditor;
import com.archimatetool.editor.model.viewpoints.IViewpoint;
import com.archimatetool.editor.model.viewpoints.ViewpointsManager;
import com.archimatetool.editor.preferences.IPreferenceConstants;
import com.archimatetool.editor.preferences.Preferences;
import com.archimatetool.editor.ui.ColorFactory;
import com.archimatetool.model.IArchimateDiagramModel;
import com.archimatetool.model.IArchimateElement;
import com.archimatetool.model.IArchimateModel;
import com.archimatetool.model.IRelationship;



/**
 * Provides Tree filtering support when a Viewpoint is selected
 * 
 * @author Phillip Beauvoir
 */
public class TreeViewpointFilterProvider implements IPartListener {

    /**
     * Active Diagram Model
     */
    private IArchimateDiagramModel fActiveDiagramModel;
    
    /**
     * Tree Viewer
     */
    private TreeViewer fViewer;
    
    /**
     * Application Preferences Listener
     */
    private IPropertyChangeListener prefsListener = new IPropertyChangeListener() {
        @Override
        public void propertyChange(PropertyChangeEvent event) {
            if(IPreferenceConstants.VIEWPOINTS_FILTER_MODEL_TREE.equals(event.getProperty())) {
                fViewer.refresh();
            }
        }
    };
    
    TreeViewpointFilterProvider(TreeViewer viewer) {
        PlatformUI.getWorkbench().getActiveWorkbenchWindow().getPartService().addPartListener(this);
        fViewer = viewer;

        // Listen to Preferences
        Preferences.STORE.addPropertyChangeListener(prefsListener);
        fViewer.getControl().addDisposeListener(new DisposeListener() {
            @Override
            public void widgetDisposed(DisposeEvent e) {
            	if(PlatformUI.getWorkbench().getActiveWorkbenchWindow() != null) {
            		PlatformUI.getWorkbench().getActiveWorkbenchWindow().getPartService().removePartListener(TreeViewpointFilterProvider.this);
            	}
                
                Preferences.STORE.removePropertyChangeListener(prefsListener);
            }
        });
    }
    
    /**
     * Refresh the Archimate model in the tree
     */
    private void refreshTreeModel(IArchimateDiagramModel dm) {
        if(dm != null && isActive()) {
            IArchimateModel model = dm.getArchimateModel();
            fViewer.refresh(model);
        }
    }

    @Override
    public void partActivated(IWorkbenchPart part) {
        /*
         * Refresh Tree only if an IEditorPart is activated.
         * 
         * If we call refresh() when a ViewPart is activated then a problem occurs when:
         * 1. User adds a new Diagram View to the Tree
         * 2. Element is added to model - refresh() is called on Tree
         * 3. Diagram Editor is opened and activated
         * 4. This is notified of Diagram Editor Part activation and calls refresh() on Tree
         * 5. NewDiagramCommand.execute() calls TreeModelViewer.editElement() to edit the cell name
         * 6. The Tree is then activated and This is notified of Diagram Editor Part activation and calls refresh() on Tree
         * 7. TreeModelViewer.refresh(element) then cancels editing
         */
        if(part instanceof IEditorPart) {
            IArchimateDiagramModel previous = fActiveDiagramModel;

            // Archimate editor
            if(part instanceof IArchimateDiagramEditor) {
                IArchimateDiagramModel dm = (IArchimateDiagramModel)((IArchimateDiagramEditor)part).getModel();
                
                if(previous == dm) {
                    return;
                }
                
                fActiveDiagramModel = dm;
            }
            // Other type of editor (sketch, canvas)
            else {
                fActiveDiagramModel = null;
            }
            
            // Refresh previous model
            refreshTreeModel(previous);

            // Refresh selected model
            refreshTreeModel(fActiveDiagramModel);
        }
    }

    @Override
    public void partBroughtToTop(IWorkbenchPart part) {
    }

    @Override
    public void partClosed(IWorkbenchPart part) {
        // Check if no editors open
        if(part instanceof IEditorPart) {
        	if(PlatformUI.getWorkbench().getActiveWorkbenchWindow() != null) {
        		IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
                if(page != null && page.getActiveEditor() == null) {
                    fActiveDiagramModel = null;
                    if(isActive()) {
                        fViewer.refresh();
                    }
                }
        	}
        }
    }

    @Override
    public void partDeactivated(IWorkbenchPart part) {
    }

    @Override
    public void partOpened(IWorkbenchPart part) {
    }

    /**
     * If the element is disallowed in a Viewpoint grey it out
     * @param element
     * @return Color or null
     */
    public Color getTextColor(Object element) {
        if(isActive() && fActiveDiagramModel != null && element instanceof IArchimateElement) {
            int index = fActiveDiagramModel.getViewpoint();
            IViewpoint viewpoint = ViewpointsManager.INSTANCE.getViewpoint(index);
            if(viewpoint != null) {
                // From same model as active diagram
                IArchimateModel model = ((IArchimateElement)element).getArchimateModel();
                if(model == fActiveDiagramModel.getArchimateModel()) {
                    if(element instanceof IRelationship) {
                        IArchimateElement source = ((IRelationship)element).getSource();
                        IArchimateElement target = ((IRelationship)element).getTarget();
                        if(!viewpoint.isAllowedType(source.eClass()) || !viewpoint.isAllowedType(target.eClass())) {
                            return ColorFactory.get(128, 128, 128);
                        }
                    }
                    else {
                        if(!viewpoint.isAllowedType(((IArchimateElement)element).eClass())) {
                            return ColorFactory.get(128, 128, 128);
                        }
                    }
                }
            }
        }

        return null;
    }
    
    boolean isActive() {
        return Preferences.STORE.getBoolean(IPreferenceConstants.VIEWPOINTS_FILTER_MODEL_TREE);
    }
}

@@ -2092,24 +2092,142 @@
  viewer) %7B%0D%0A
+        fViewer = viewer;%0D%0A%0D%0A        // Listen to Part selections%0D%0A        if(PlatformUI.isWorkbenchRunning()) %7B%0D%0A    
         Plat
@@ -2324,35 +2324,27 @@
         
-fViewer = viewer;%0D%0A
+%7D%0D%0A        
 %0D%0A      
@@ -2432,32 +2432,34 @@
 refsListener);%0D%0A
+%0D%0A
         fViewer.
@@ -2604,32 +2604,67 @@
             %09if(
+PlatformUI.isWorkbenchRunning() && 
 PlatformUI.getWo

Remove hard dependency on PlatformUI Workbench