blob: 864b6b36d21b2571c084400957c02bb435e640b0 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2016 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Lars Vogel <Lars.Vogel@gmail.com> - Bug 440810
*******************************************************************************/
package org.eclipse.ui.internal;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.ui.IPropertyListener;
import org.eclipse.ui.contexts.IContextActivation;
import org.eclipse.ui.contexts.IContextService;
import org.eclipse.ui.internal.registry.IActionSetDescriptor;
import org.eclipse.ui.services.IServiceLocator;
/**
* Maintains a reference counted set of action sets, with a visibility mask.
* This is used to determine the visibility of actions in a workbench page. In a
* workbench page, there may be may be many conditions that can cause an action
* set to become visible (such as the active part, the active editor, the
* default visibility of the action, the properties of the perspective, etc.)
* The user can also explicitly mask off particular action sets in each
* perspective.
* <p>
* The reference count indicates how many conditions have requested that the
* actions be active and the mask indicates whether or not the set was disabled
* by the user.
* </p>
*
* @since 3.1
*/
public class ActionSetManager {
private static class ActionSetRec {
int showCount;
int maskCount;
public boolean isVisible() {
return maskCount == 0 && showCount > 0;
}
public boolean isEmpty() {
return maskCount == 0 && showCount == 0;
}
}
private HashMap actionSets = new HashMap();
private HashSet visibleItems = new HashSet();
public static final int PROP_VISIBLE = 0;
public static final int PROP_HIDDEN = 1;
public static final int CHANGE_MASK = 0;
public static final int CHANGE_UNMASK = 1;
public static final int CHANGE_SHOW = 2;
public static final int CHANGE_HIDE = 3;
private ListenerList<IPropertyListener> listeners = new ListenerList<>();
private IPropertyListener contextListener;
private Map activationsById = new HashMap();
private IContextService contextService;
public ActionSetManager(IServiceLocator locator) {
contextService = locator.getService(IContextService.class);
addListener(getContextListener());
}
/**
* @return
*/
private IPropertyListener getContextListener() {
if (contextListener == null) {
contextListener = (source, propId) -> {
if (source instanceof IActionSetDescriptor) {
IActionSetDescriptor desc = (IActionSetDescriptor) source;
String id = desc.getId();
if (propId == PROP_VISIBLE) {
activationsById.put(id, contextService.activateContext(id));
} else if (propId == PROP_HIDDEN) {
IContextActivation act = (IContextActivation) activationsById.remove(id);
if (act != null) {
contextService.deactivateContext(act);
}
}
}
};
}
return contextListener;
}
public void addListener(IPropertyListener l) {
listeners.add(l);
}
public void removeListener(IPropertyListener l) {
listeners.remove(l);
}
private void firePropertyChange(IActionSetDescriptor descriptor, int id) {
for (IPropertyListener listener : listeners) {
listener.propertyChanged(descriptor, id);
}
}
private ActionSetRec getRec(IActionSetDescriptor descriptor) {
ActionSetRec rec = (ActionSetRec) actionSets.get(descriptor);
if (rec == null) {
rec = new ActionSetRec();
actionSets.put(descriptor, rec);
}
return rec;
}
public void showAction(IActionSetDescriptor descriptor) {
ActionSetRec rec = getRec(descriptor);
boolean wasVisible = rec.isVisible();
rec.showCount++;
if (!wasVisible && rec.isVisible()) {
visibleItems.add(descriptor);
firePropertyChange(descriptor, PROP_VISIBLE);
if (rec.isEmpty()) {
actionSets.remove(descriptor);
}
}
}
public void hideAction(IActionSetDescriptor descriptor) {
ActionSetRec rec = getRec(descriptor);
boolean wasVisible = rec.isVisible();
rec.showCount--;
if (wasVisible && !rec.isVisible()) {
visibleItems.remove(descriptor);
firePropertyChange(descriptor, PROP_HIDDEN);
if (rec.isEmpty()) {
actionSets.remove(descriptor);
}
}
}
public void maskAction(IActionSetDescriptor descriptor) {
ActionSetRec rec = getRec(descriptor);
boolean wasVisible = rec.isVisible();
rec.maskCount++;
if (wasVisible && !rec.isVisible()) {
visibleItems.remove(descriptor);
firePropertyChange(descriptor, PROP_HIDDEN);
if (rec.isEmpty()) {
actionSets.remove(descriptor);
}
}
}
public void unmaskAction(IActionSetDescriptor descriptor) {
ActionSetRec rec = getRec(descriptor);
boolean wasVisible = rec.isVisible();
rec.maskCount--;
if (!wasVisible && rec.isVisible()) {
visibleItems.add(descriptor);
firePropertyChange(descriptor, PROP_VISIBLE);
if (rec.isEmpty()) {
actionSets.remove(descriptor);
}
}
}
public Collection getVisibleItems() {
return visibleItems;
}
public void change(IActionSetDescriptor descriptor, int changeType) {
switch (changeType) {
case CHANGE_SHOW:
showAction(descriptor);
break;
case CHANGE_HIDE:
hideAction(descriptor);
break;
case CHANGE_MASK:
maskAction(descriptor);
break;
case CHANGE_UNMASK:
unmaskAction(descriptor);
break;
}
}
}