 /**
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * Copyright © 2009 Mindoo GmbH
 *
 * @author Tammo Riedinger
 *
 */
package com.mindoo.ec09.example3;

import java.util.ArrayList;
import java.util.HashMap;

import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;

/**
 * Class to show/hide actionsets for a {@link IWorkbenchPart}.<br>
 * This class hides the actionsets when the part is deactivated, and activates them
 * again, when the part is activated.
 * 
 * @author Tammo Riedinger
 *
 */
public abstract class ActionSetManager {
	private IWorkbenchPart m_part;
	private HashMap<String,String> m_activeActionsSets=new HashMap<String,String>();
	private IPartListener m_partListener;

	/**
	 * Creates an instance of this class.
	 * 
	 * @param part		part whose activation/deactivation is being monitored
	 */
	public ActionSetManager(IWorkbenchPart part) {
		m_part=part;
		
		// install the listener to monitor the part
		m_part.getSite().getPage().addPartListener(new IPartListener() {
			public void partActivated(final IWorkbenchPart part) {
				if (part==m_part)
					update();
			}
			
			public void partDeactivated(IWorkbenchPart part) {
				ActionSetManager.this.hideAllActionSets(part);
			}

			public void partBroughtToTop(IWorkbenchPart part) {
			}

			public void partClosed(IWorkbenchPart part) {
				ActionSetManager.this.hideAllActionSets(part);
			}

			public void partOpened(IWorkbenchPart part) {
			}
		});
	}
	
	/**
	 * Dispose this class and its used resources.
	 */
	public void dispose() {
		if (m_partListener!=null && m_part!=null) {
			m_part.getSite().getPage().removePartListener(m_partListener);
			m_partListener=null;
			m_part=null;
		}
	}
	
	/**
	 * Call this method to deactivate all actionsets for the part.
	 * 
	 * @param part		the part
	 */
	private void hideAllActionSets(IWorkbenchPart part) {
		if (part==m_part)
			hideActionSets(m_activeActionsSets.keySet().toArray(new String[0]));
	}
	
	/**
	 * Call this method to deactivate the given actionsets.
	 * 
	 * @param actionSetIDs		ids of the sets to be hidden
	 */
	protected void hideActionSets(String[] actionSetIDs) {
		// de-activate all active action sets
		IWorkbenchPage page=m_part.getSite().getPage();
						
		for (String id:actionSetIDs) {
			m_activeActionsSets.remove(id);
				
			page.hideActionSet(id);
		}
	}
	
	/**
	 * Method to be called in order to hide/show the actionsets.<br>
	 * This method queries {@link #getActiveActionSetIDs()} to determine the actionsets
	 * that are active at this point.<br>
	 * Subclasses have to implement this method
	 */
	public void update() {
		String[] newIDs=getActiveActionSetIDs();
		
		HashMap<String,String> newIDsMap=new HashMap<String,String>();
		// find new actionsets that needs to be activated
		HashMap<String,String> activeIDs=new HashMap<String,String>();
		for (String id:newIDs) {
			newIDsMap.put(id,id);
			if (!m_activeActionsSets.containsKey(id))
				activeIDs.put(id,id);
		}
		
		// find actionsets that need to be deactivated
		ArrayList<String> inactveIDs=new ArrayList<String>();
		for (String id:m_activeActionsSets.values()) {
			if (!newIDsMap.containsKey(id))
				inactveIDs.add(id);
		}
		
		IWorkbenchPage page=m_part.getSite().getPage();
		
		// de-activate the action sets while keeping track of them
		for (String id:inactveIDs) {
			m_activeActionsSets.remove(id);
			
			page.hideActionSet(id);
		}

		// activate the sets when the part is still active at this point
		IWorkbenchWindow activeWindow=PlatformUI.getWorkbench().getActiveWorkbenchWindow();
		if (activeWindow==null)
			return;
		
		IWorkbenchPage activePage=activeWindow.getActivePage();
		if (activePage==null)
			return;
		
		IWorkbenchPart activePart=activePage.getActivePart();
		if (activePart!=m_part)
			return;
		
		// activate the action sets while keeping track of them
		for (String id:activeIDs.values()) {
			activePage.showActionSet(id);
			
			m_activeActionsSets.put(id,id);
		}
	}
	
	/**
	 * Method being queried for the active actionsets at the time of the method call.
	 * 
	 * @return			active actionsets
	 */
	protected abstract String[] getActiveActionSetIDs();
}
