/******************************************************************************* * Copyright (c) 2005, 2008 IBM Corporation 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: * P.Tomaszewski * Anton Leherbauer (Wind River Systems) * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.actions; import java.util.ResourceBundle; import org.eclipse.jface.text.ITextSelection; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.texteditor.ITextEditor; import org.eclipse.ui.texteditor.TextEditorAction; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.IParent; import org.eclipse.cdt.core.model.ISourceRange; import org.eclipse.cdt.core.model.ISourceReference; import org.eclipse.cdt.core.model.IWorkingCopy; import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.internal.ui.editor.CEditor; /** * Gives possibility to move fast between member elements of the c/c++ source. * * @author P.Tomaszewski */ public class GoToNextPreviousMemberAction extends TextEditorAction { public static final String NEXT_MEMBER = "GotoNextMember"; //$NON-NLS-1$ public static final String PREVIOUS_MEMBER = "GotoPrevMember"; //$NON-NLS-1$ /** Determines should action take user to the next member or to the previous one. */ private boolean fGotoNext; /** * Creates new action. * @param bundle Resource bundle. * @param prefix Prefix. * @param editor Editor. * @param gotoNext Is it go to next or previous action. */ public GoToNextPreviousMemberAction(ResourceBundle bundle, String prefix, ITextEditor editor, boolean gotoNext) { super(bundle, prefix, editor); fGotoNext = gotoNext; } /** * Creates new action. * @param bundle Resource bundle. * @param prefix Prefix. * @param editor Editor. * @param style UI style. * @param gotoNext Is it go to next or previous action. */ public GoToNextPreviousMemberAction(ResourceBundle bundle, String prefix, ITextEditor editor, int style, boolean gotoNext) { super(bundle, prefix, editor, style); fGotoNext = gotoNext; } /* * @see org.eclipse.ui.texteditor.TextEditorAction#update() */ @Override public void update() { final ITextEditor editor = getTextEditor(); setEnabled(editor instanceof CEditor && ((CEditor)editor).getInputCElement() != null); } /** * @see org.eclipse.jface.action.Action#run() */ @Override public void run() { final CEditor editor = (CEditor) getTextEditor(); final ITextSelection selection = (ITextSelection) editor.getSelectionProvider().getSelection(); final IEditorInput editorInput = editor.getEditorInput(); final IWorkingCopy workingCopy = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(editorInput); if (workingCopy == null) { return; } try { ISourceReference next= fGotoNext ? getNextElement(workingCopy, selection.getOffset()) : getPrevElement(workingCopy, selection.getOffset()); if (next != null) { editor.selectAndReveal(next.getSourceRange().getIdStartPos(), 0); } } catch (CModelException e) { CUIPlugin.log(e); } } private ISourceReference getNextElement(IParent parent, int offset) throws CModelException { ICElement[] children= parent.getChildren(); for (int i = 0; i < children.length; i++) { ICElement element = children[i]; if (element instanceof ISourceReference) { final ISourceReference candidate1= (ISourceReference) element; final ISourceRange range= candidate1.getSourceRange(); final int idpos1= range.getIdStartPos(); if (element instanceof IParent && range.getStartPos() + range.getLength() > offset) { ISourceReference candidate2= getNextElement((IParent) element, offset); if (candidate2 != null) { final int idpos2= candidate2.getSourceRange().getIdStartPos(); if (idpos1 <= offset || idpos1 > idpos2) { return candidate2; } } } if (idpos1 > offset) { return candidate1; } } } return null; } private ISourceReference getPrevElement(IParent parent, int offset) throws CModelException { ICElement[] children= parent.getChildren(); for (int i= children.length-1; i >= 0; i--) { ICElement element = children[i]; if (element instanceof ISourceReference) { final ISourceReference candidate1= (ISourceReference) element; final ISourceRange range= candidate1.getSourceRange(); final int idpos1= range.getIdStartPos(); if (element instanceof IParent && range.getStartPos() < offset) { ISourceReference candidate2= getPrevElement((IParent) element, offset); if (candidate2 != null) { final int idpos2= candidate2.getSourceRange().getIdStartPos(); if (idpos1 >= offset || idpos1 < idpos2) { return candidate2; } } } if (idpos1 < offset) { return candidate1; } } } return null; } }