blob: a2bc83115607a772c649599163691a5e3fb06572 [file] [log] [blame]
/**********************************************************************
* This file is part of "Object Teams Development Tooling"-Software
*
* Copyright 2004, 2008 Fraunhofer Gesellschaft, Munich, Germany,
* for its Fraunhofer Institute for Computer Architecture and Software
* Technology (FIRST), Berlin, Germany and Technical University Berlin,
* Germany.
*
* 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
* $Id: UpdateRulerAction.java 23435 2010-02-04 00:14:38Z stephan $
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
* Contributors:
* Fraunhofer FIRST - Initial API and implementation
* Technical University Berlin - Initial API and implementation
**********************************************************************/
package org.eclipse.objectteams.otdt.ui;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
import org.eclipse.jdt.internal.ui.javaeditor.IClassFileEditorInput;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.source.IVerticalRulerInfo;
import org.eclipse.objectteams.otdt.core.IOTType;
import org.eclipse.objectteams.otdt.core.IRoleType;
import org.eclipse.objectteams.otdt.core.OTModelManager;
import org.eclipse.objectteams.otdt.internal.ui.callinmarkers.CallinMarker;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.texteditor.AbstractRulerActionDelegate;
import org.eclipse.ui.texteditor.ITextEditor;
/**
* Action that is executed when the user right clicks on a binding marker at
* the vertical ruler and chooses a mapping (bound role class or callin mapping)
* from the ObjectTeams submenu.
*
* @author brcan
* @version $Id: UpdateRulerAction.java 23435 2010-02-04 00:14:38Z stephan $
*/
public class UpdateRulerAction extends AbstractRulerActionDelegate
{
public final static String OT_PLAYEDBY_MENU_LABEL = OTDTUIPlugin.getResourceString("CallinMarker.menu_playedby_title"); //$NON-NLS-1$
public final static String OT_CALLIN_MENU_LABEL = OTDTUIPlugin.getResourceString("CallinMarker.menu_callin_title"); //$NON-NLS-1$
public final static String OT_CALLOUT_MENU_LABEL = OTDTUIPlugin.getResourceString("CallinMarker.menu_callout_title"); //$NON-NLS-1$
private IEditorPart _editor = null;
private IVerticalRulerInfo _rulerInfo = null;
public UpdateRulerAction()
{
}
public void setActiveEditor(IAction callerAction, IEditorPart targetEditor)
{
_editor = targetEditor;
super.setActiveEditor(callerAction, targetEditor);
}
protected IAction createAction(ITextEditor editor, IVerticalRulerInfo rulerInfo)
{
_rulerInfo = rulerInfo;
return null;
}
public void menuAboutToShow(IMenuManager contextMenu)
{
try
{
IMarker[] markers = findMarkers();
if (markers != null && markers.length != 0)
{
Integer clickedLine = new Integer(_rulerInfo.getLineOfLastMouseButtonActivity() + 1);
IDocument document = null;
if (this._editor instanceof ITextEditor) {
ITextEditor textEditor = (ITextEditor) this._editor;
document= textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput());
}
for (int idx = 0; idx < markers.length; idx++)
{
IMarker curMarker = markers[idx];
Object lineAttribute = curMarker.getAttribute(IMarker.LINE_NUMBER);
if (lineAttribute != null)
{
if (lineAttribute.equals(clickedLine))
insertTeamMenus(contextMenu, curMarker);
} else if (document != null) {
// markers in ClassFileEditor have no line number, must go via position:
Integer startAttribute = (Integer) curMarker.getAttribute(IMarker.CHAR_START);
try {
if (clickedLine.equals(document.getLineOfOffset(startAttribute)+1))
insertTeamMenus(contextMenu, curMarker);
}
catch (BadLocationException e) { /* nop */ }
}
}
}
}
catch (CoreException ex)
{
OTDTUIPlugin.getExceptionHandler().logCoreException("Problems extending ruler context menu", ex); //$NON-NLS-1$
}
}
private IMarker[] findMarkers() throws CoreException
{
final IEditorInput editorInput = _editor.getEditorInput();
if (editorInput instanceof IFileEditorInput)
{
IFileEditorInput fileEditorInput = (IFileEditorInput)editorInput;
IFile file = fileEditorInput.getFile();
IMarker[] result = getAllBindingMarkers(file);
return result;
}
else if (editorInput instanceof IClassFileEditorInput)
{
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
IMarker[] allMarkers = getAllBindingMarkers(root);
// now we have all CallinMarkers for all class files in the workspace, need to filter now:
IClassFile classFile = ((IClassFileEditorInput) editorInput).getClassFile();
List<IMarker> filteredMarkers = new ArrayList<IMarker>(13);
for (IMarker marker : allMarkers)
if (JavaCore.isReferencedBy(classFile, marker))
filteredMarkers.add(marker);
return filteredMarkers.toArray(new IMarker[filteredMarkers.size()]);
}
return null;
}
/** get all playedBy and callin markers for the given resource. */
private IMarker[] getAllBindingMarkers(IResource resource) throws CoreException {
IMarker[] markers1 = resource.findMarkers(CallinMarker.PLAYEDBY_ID, true, IResource.DEPTH_INFINITE);
IMarker[] markers2 = resource.findMarkers(CallinMarker.CALLIN_ID, true, IResource.DEPTH_INFINITE);
IMarker[] markers3 = resource.findMarkers(CallinMarker.CALLOUT_ID, true, IResource.DEPTH_INFINITE);
int len1 = markers1.length, len2 = markers2.length, len3 = markers3.length;
IMarker[] result = new IMarker[len1+len2+len3];
System.arraycopy(markers1, 0, result, 0, len1);
System.arraycopy(markers2, 0, result, len1, len2);
System.arraycopy(markers3, 0, result, len1+len2, len3);
return result;
}
/** Get the context menu of kind 'markerKind', creating it if ondemand. */
private IMenuManager getObjectTeamsMenu(IMenuManager contextMenu, String markerKind)
{
String label;
if (CallinMarker.CALLIN_ID.equals(markerKind))
label = OT_CALLIN_MENU_LABEL;
else if (CallinMarker.CALLOUT_ID.equals(markerKind))
label = OT_CALLOUT_MENU_LABEL;
else
label = OT_PLAYEDBY_MENU_LABEL;
IMenuManager subMenu = getSubMenu(contextMenu, label);
if (subMenu != null)
return subMenu;
MenuManager otMenu = new MenuManager(label, markerKind); // id cannot be null, re-use the markerKind
if (contextMenu.isEmpty())
contextMenu.add(otMenu);
else // insert on top
contextMenu.insertBefore(contextMenu.getItems()[0].getId(), otMenu);
return otMenu;
}
private IAction createOpenEditorAction(String label, final IJavaElement target)
{
Action result = new Action(label)
{
public void run()
{
try
{
IEditorPart part = EditorUtility.openInEditor(target);
if (target.exists()) // also initializes source positions if necessary
EditorUtility.revealInEditor(part, target);
}
catch (PartInitException ex)
{
OTDTUIPlugin.getExceptionHandler().logException("Problems initializing editor", ex); //$NON-NLS-1$
}
}
};
return result;
}
List<IMember> getMappings (IMarker marker) throws CoreException
{
Object attr = marker.getAttribute(CallinMarker.ATTR_ROLE_ELEMENTS);
if (attr == null || !(attr instanceof String))
return null;
String str = (String)attr;
List<IMember> result = new ArrayList<IMember>();
int start = 0;
int pos;
while ((pos = str.indexOf('\n', start)) != -1) {
result.add((IMember)JavaCore.create(str.substring(start, pos)));
start = pos+1;
}
return result;
}
private void insertTeamMenus(IMenuManager contextMenu, IMarker marker) throws CoreException
{
List<IMember> mappings = getMappings(marker);
if (mappings == null) return;
IMenuManager otMenu = getObjectTeamsMenu(contextMenu, marker.getType());
for (IMember curMapping : mappings)
{
IType type = (IType)(curMapping.getAncestor(IJavaElement.TYPE));
IOTType otType = OTModelManager.getOTElement(type); // FIXME(SH): doesn't find role files??? (try StubUtility2)
if (otType == null || !otType.isRole())
continue;
IOTType teamType = ((IRoleType) otType).getTeam();
IMenuManager curTeamMenu = null;
if (!isSubMenuContained(otMenu, teamType.getElementName()))
{
curTeamMenu = new MenuManager(teamType.getElementName());
otMenu.add(curTeamMenu);
}
else
{
curTeamMenu = getSubMenu(otMenu, teamType.getElementName());
}
String actLabel = getMappingLabel(type, curMapping);
curTeamMenu.add(createOpenEditorAction(actLabel, curMapping));
}
}
private String getMappingLabel(IType type, IMember mapping)
{
if (type.equals(mapping)) return type.getElementName();
return type.getElementName() + ": " + mapping.getElementName(); //$NON-NLS-1$
}
private IMenuManager getSubMenu(IMenuManager otMenu, String subMenuName)
{
if (otMenu == null)
return null;
IContributionItem[] items = otMenu.getItems();
for (int idx = 0; idx < items.length; idx++)
{
if (items[idx] instanceof IMenuManager)
{
MenuManager cur = (MenuManager)items[idx];
if (cur.getMenuText().equals(subMenuName))
{
return cur;
}
}
}
return null;
}
private boolean isSubMenuContained(IMenuManager menu, String subMenuName)
{
return getSubMenu(menu, subMenuName) != null;
}
}