| /**************************************************************************** |
| * 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); |
| } |
| |
| } |