blob: 937a3e1a6b65d18cd0f6edfe752c799113ba998b [file] [log] [blame]
/****************************************************************************
* Copyright (c) 2007 Composent, Inc. 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:
* Composent, Inc. - initial API and implementation
*****************************************************************************/
package org.eclipse.ecf.presence.ui.menu;
import java.util.*;
import org.eclipse.core.commands.Command;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.runtime.Assert;
import org.eclipse.ecf.core.IContainer;
import org.eclipse.ecf.core.IContainerManager;
import org.eclipse.ecf.internal.presence.ui.Activator;
import org.eclipse.ecf.presence.IPresence;
import org.eclipse.ecf.presence.IPresenceContainerAdapter;
import org.eclipse.ecf.presence.roster.*;
import org.eclipse.ecf.ui.SharedImages;
import org.eclipse.jface.action.*;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.CompoundContributionItem;
import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.menus.CommandContributionItem;
import org.eclipse.ui.menus.CommandContributionItemParameter;
import org.eclipse.ui.services.IServiceLocator;
/**
* A contribution that dynamically constructs a menu for the currently connected rosters.
* This class may be subclassed in order to create a {@link AbstractRosterMenuHandler} for
* handling selection of a given {@link IRosterEntry} from the menu.
*/
public abstract class AbstractRosterMenuContributionItem extends CompoundContributionItem {
private static final String DEFAULT_TOP_MENU_NAME = "Share"; //$NON-NLS-1$
protected static final IContributionItem[] NO_CONTRIBUTIONS = new IContributionItem[] {};
private static final String ROSTERCOMMAND_PREFIX = "org.eclipse.ecf.presence.ui.rosterCommand."; //$NON-NLS-1$
private static final List handlerActivations = new ArrayList();
private static int commandIdIndex = 0;
private IServiceLocator serviceLocator;
private IHandlerService handlerService;
private ICommandService commandService;
private String topMenuName = DEFAULT_TOP_MENU_NAME;
private ImageDescriptor topMenuImageDescriptor = Activator.getDefault().getImageRegistry().getDescriptor(Activator.COLLABORATION_IMAGE);
protected void setTopMenuName(String name) {
this.topMenuName = name;
}
public void setTopMenuImageDescriptor(ImageDescriptor image) {
this.topMenuImageDescriptor = image;
}
protected ImageDescriptor getTopMenuImageDescriptor() {
return this.topMenuImageDescriptor;
}
private void initialize() {
serviceLocator = PlatformUI.getWorkbench();
Assert.isNotNull(serviceLocator);
handlerService = (IHandlerService) serviceLocator.getService(IHandlerService.class);
Assert.isNotNull(handlerService);
commandService = (ICommandService) serviceLocator.getService(ICommandService.class);
Assert.isNotNull(commandService);
}
public AbstractRosterMenuContributionItem() {
initialize();
}
public AbstractRosterMenuContributionItem(String id) {
super(id);
initialize();
}
/**
* Create contribution items for a given roster. Subclasses may override as appropriate
* to customize the creation of contributions with an alternative strategy.
* @param roster the roster to create contribution items for. Must not be <code>null</code>.
* @return IContributionItem[] for given IRoster. Will not return <code>null</code>.
*
*/
protected IContributionItem[] createContributionItemsForRoster(IRoster roster) {
Collection rosterItems = roster.getItems();
List contributions = new ArrayList();
for (Iterator i = rosterItems.iterator(); i.hasNext();) {
IRosterItem item = (IRosterItem) i.next();
IContributionItem[] adds = null;
if (item instanceof IRosterEntry) {
adds = createContributionItemsForEntry((IRosterEntry) item);
} else if (item instanceof IRosterGroup) {
adds = createContributionItemsForGroup((IRosterGroup) item);
}
if (adds != null) {
for (int j = 0; j < adds.length; j++) {
contributions.add(adds[j]);
}
}
}
return (IContributionItem[]) contributions.toArray(new IContributionItem[] {});
}
/**
* Create contribution items for a given roster. Subclasses may override as appropriate
* to customize the creation of contributions with an alternative strategy.
* @param group the IRosterGroup to create contribution items for. Must not be <code>null</code>.
* @return IContributionItem[] for given IRosterGroup. Will not return <code>null</code>.
*
*/
protected IContributionItem[] createContributionItemsForGroup(IRosterGroup group) {
Collection entries = group.getEntries();
MenuManager menuManager = null;
for (Iterator i = entries.iterator(); i.hasNext();) {
IRosterEntry entry = (IRosterEntry) i.next();
IContributionItem[] menuContributions = createContributionItemsForEntry(entry);
if (menuContributions != null && menuContributions.length > 0) {
for (int j = 0; j < menuContributions.length; j++) {
if (menuManager == null) {
menuManager = createMenuManagerForGroup(group);
}
menuManager.add(menuContributions[j]);
}
}
}
if (menuManager != null)
return new IContributionItem[] {menuManager};
return NO_CONTRIBUTIONS;
}
/**
* Create a MenuManager for the given {@link IRosterGroup}.
* @param group the IRosterGroup to create the menu manager for. Will not be <code>null</code>.
* @return the menu manager. Should not be <code>null</code>.
*/
protected MenuManager createMenuManagerForGroup(IRosterGroup group) {
return new MenuManager(group.getName());
// XXX 3.4 constructor return new MenuManager(group.getName(), SharedImages.getImageDescriptor(SharedImages.IMG_GROUP), null);
}
/**
* Create contribution items for a given presence container adapter. Subclasses may override as
* appropriate to customize the creation of contributions with an alternative strategy.
* @param presenceContainerAdapter the IPresenceContainerAdapter to create contribution items for. Must not be <code>null</code>.
* @return IContributionItem[] for given IPresenceContainerAdapter. Will not return <code>null</code>.
*
*/
protected IContributionItem[] createContributionItemsForPresenceContainer(IPresenceContainerAdapter presenceContainerAdapter) {
IRoster roster = presenceContainerAdapter.getRosterManager().getRoster();
IContributionItem[] contributions = createContributionItemsForRoster(roster);
if (contributions == null || contributions.length == 0)
return NO_CONTRIBUTIONS;
MenuManager menuManager = createMenuManagerForRoster(roster);
for (int i = 0; i < contributions.length; i++) {
menuManager.add(contributions[i]);
}
return new IContributionItem[] {menuManager};
}
/**
* Create a MenuManager for the given {@link IRosterGroup}.
* @param roster the IRosterGroup to create the menu manager for. Will not be <code>null</code>.
* @return the menu manager. Should not be <code>null</code>.
*/
protected MenuManager createMenuManagerForRoster(IRoster roster) {
// 3.4 constructor return new MenuManager(roster.getUser().getName(), SharedImages.getImageDescriptor(SharedImages.IMG_IDENTITY), null);
return new MenuManager(roster.getUser().getName());
}
private int getNextCommandIdIndex() {
return commandIdIndex++;
}
/**
* Create a {@link AbstractRosterMenuHandler} for a given IRosterEntry instance. Implementers of this method
* should construct and return a new {@link AbstractRosterMenuHandler}. When a menu selection is made for
* a given {@link IRosterEntry} menu item, the associated {@link AbstractRosterMenuHandler} instance will have its
* {@link AbstractRosterMenuHandler#execute(org.eclipse.core.commands.ExecutionEvent)} method will
* be called. This way, subclasses may define arbitrary behavior for the dynamic menu item
* selection.
*
* @param rosterEntry the {@link IRosterEntry} for the {@link AbstractRosterMenuHandler}. Will not be <code>null</code>.
* @return {@link AbstractRosterMenuHandler} instance. Must not be <code>null</code>.
*/
protected abstract AbstractRosterMenuHandler createRosterEntryHandler(IRosterEntry rosterEntry);
/**
* Determines whether given entry should be added for IContribution. This implementation only
* returns <code>true</code> if the given {@link IRosterEntry#getPresence()} IPresence.Type is
* AVAILABLE, and IPresence.Mode is AVAILABLE. Subclasses may override as appropriate
* to customize the behavior of this contribution item.
*
* @param entry the IRosterEntry to check. Must not be <code>null</code>.
* @return <code>true</code> if the given IRosterEntry should be added, <code>false</code> otherwise.
*/
protected boolean addEntry(IRosterEntry entry) {
IPresence presence = entry.getPresence();
if (presence == null)
return false;
return (presence.getType().equals(IPresence.Type.AVAILABLE) && presence.getMode().equals(IPresence.Mode.AVAILABLE));
}
/**
* Create contribution items for a given roster entry. Subclasses may override as
* appropriate to customize the creation of contributions with an alternative strategy.
* @param entry the IRosterEntry to create contribution items for. Must not be <code>null</code>.
* @return IContributionItem[] for given IPresenceContainerAdapter. Will not return <code>null</code>.
*
*/
protected IContributionItem[] createContributionItemsForEntry(IRosterEntry entry) {
if (addEntry(entry)) {
String commandId = ROSTERCOMMAND_PREFIX + getNextCommandIdIndex();
// Get existing/new command
Command command = commandService.getCommand(commandId);
command.define(commandId, null, commandService.getCategory(commandId + ".c")); //$NON-NLS-1$
IHandler handler = command.getHandler();
// Only mess with it if it was of old type
if (handler != null && handler instanceof AbstractRosterMenuHandler) {
AbstractRosterMenuHandler drh = (AbstractRosterMenuHandler) handler;
if (drh != null) {
drh.fireHandlerChangeEvent();
drh.dispose();
}
}
IHandler newHandler = createRosterEntryHandler(entry);
command.setHandler(newHandler);
handlerActivations.add(handlerService.activateHandler(commandId, newHandler));
return new IContributionItem[] {createCommandContributionItemForEntry(commandId, entry)};
}
return NO_CONTRIBUTIONS;
}
protected ImageDescriptor getRosterEntryImageDescriptor(IRosterEntry entry) {
IPresence p = entry.getPresence();
if (p != null) {
IPresence.Type pType = p.getType();
IPresence.Mode pMode = p.getMode();
// If type is unavailable then we're unavailable
if (pType.equals(IPresence.Type.AVAILABLE)) {
// if type and mode are both 'available' then we're actually
// available
if (pMode.equals(IPresence.Mode.AVAILABLE))
return SharedImages.getImageDescriptor(SharedImages.IMG_USER_AVAILABLE);
// If mode is away then we're away
else if (pMode.equals(IPresence.Mode.AWAY) || pMode.equals(IPresence.Mode.EXTENDED_AWAY))
return SharedImages.getImageDescriptor(SharedImages.IMG_USER_AWAY);
else if (pMode.equals(IPresence.Mode.DND))
return SharedImages.getImageDescriptor(SharedImages.IMG_USER_DND);
}
}
return SharedImages.getImageDescriptor(SharedImages.IMG_USER_UNAVAILABLE);
}
/**
* Create a command contribution item for the given entry with the given commandId.
*
* @param commandId the commandId for the new CommandContributionItem. Must not be <code>null</code>.
* @param rosterEntry the IRosterEntry for the new CommandContributionItem. Must not be <code>null</code>.
* @return CommandContributionItem created. Must not return <code>null</code>.
*/
protected CommandContributionItem createCommandContributionItemForEntry(String commandId, IRosterEntry rosterEntry) {
CommandContributionItemParameter p = new CommandContributionItemParameter(serviceLocator, null, commandId, CommandContributionItem.STYLE_PUSH);
p.icon = getRosterEntryImageDescriptor(rosterEntry);
p.label = rosterEntry.getName();
// 3.4 return new CommandContributionItem(serviceLocator, null, commandId, new HashMap(), getRosterEntryImageDescriptor(rosterEntry), null, null, rosterEntry.getName(), null, null, CommandContributionItem.STYLE_PUSH);
return new CommandContributionItem(p);
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.ContributionItem#dispose()
*/
public void dispose() {
super.dispose();
if (handlerService != null) {
handlerService.deactivateHandlers(handlerActivations);
handlerService = null;
}
handlerActivations.clear();
commandService = null;
}
protected List getPresenceContainerAdapters() {
List presenceContainers = new ArrayList();
IContainerManager containerManager = Activator.getDefault().getContainerManager();
if (containerManager == null)
return presenceContainers;
IContainer[] containers = containerManager.getAllContainers();
for (int i = 0; i < containers.length; i++) {
IPresenceContainerAdapter presenceContainerAdapter = (IPresenceContainerAdapter) containers[i].getAdapter(IPresenceContainerAdapter.class);
if ((containers[i].getConnectedID() != null) && (presenceContainerAdapter != null)) {
presenceContainers.add(presenceContainerAdapter);
}
}
return presenceContainers;
}
/* (non-Javadoc)
* @see org.eclipse.ui.actions.CompoundContributionItem#getContributionItems()
*/
protected IContributionItem[] getContributionItems() {
// clearOldContributions();
List presenceContainers = getPresenceContainerAdapters();
if (presenceContainers.size() == 0)
return NO_CONTRIBUTIONS;
List contributions = new ArrayList();
for (Iterator i = presenceContainers.iterator(); i.hasNext();) {
IContributionItem[] items = createContributionItemsForPresenceContainer((IPresenceContainerAdapter) i.next());
for (int j = 0; j < items.length; j++)
contributions.add(items[j]);
}
if (contributions.size() > 0) {
MenuManager menuManager = createMenuManagerForTop();
IContributionItem[] items = (IContributionItem[]) contributions.toArray(new IContributionItem[] {});
for (int i = 0; i < items.length; i++)
menuManager.add(items[i]);
return new IContributionItem[] {new Separator(), menuManager};
}
return NO_CONTRIBUTIONS;
}
/**
* Create a MenuManager for the top level menu.
* @return the menu manager. Should not be <code>null</code>.
*/
protected MenuManager createMenuManagerForTop() {
// XXX 3.4 constructor return new MenuManager(topMenuName, topMenuImageDescriptor, null);
return new MenuManager(topMenuName);
}
}