--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.ui.javaeditor.selectionactions;
+
+import org.eclipse.ui.PlatformUI;
+
+import org.eclipse.jdt.core.ISourceRange;
+import org.eclipse.jdt.core.ISourceReference;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.dom.ASTNode;
+
+import org.eclipse.jdt.internal.corext.dom.GenericVisitor;
+import org.eclipse.jdt.internal.corext.dom.SelectionAnalyzer;
+
+import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
+import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
+
+public class StructureSelectPreviousAction extends StructureSelectionAction {
+
+ private static class PreviousNodeAnalyzer extends GenericVisitor {
+ private final int fOffset;
+ private ASTNode fPreviousNode;
+ private PreviousNodeAnalyzer(int offset) {
+ super(true);
+ fOffset= offset;
+ }
+ public static ASTNode perform(int offset, ASTNode lastCoveringNode) {
+ PreviousNodeAnalyzer analyzer= new PreviousNodeAnalyzer(offset);
+ lastCoveringNode.accept(analyzer);
+ return analyzer.fPreviousNode;
+ }
+ @Override
+ protected boolean visitNode(ASTNode node) {
+ int start= node.getStartPosition();
+ int end= start + node.getLength();
+ if (end == fOffset) {
+ fPreviousNode= node;
+ return true;
+ } else {
+ return (start < fOffset && fOffset < end);
+ }
+ }
+ }
+
+ public StructureSelectPreviousAction(JavaEditor editor, SelectionHistory history) {
+ super(SelectionActionMessages.StructureSelectPrevious_label, editor, history);
+ setToolTipText(SelectionActionMessages.StructureSelectPrevious_tooltip);
+ setDescription(SelectionActionMessages.StructureSelectPrevious_description);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IJavaHelpContextIds.STRUCTURED_SELECT_PREVIOUS_ACTION);
+ }
+
+ /*
+ * This constructor is for testing purpose only.
+ */
+ public StructureSelectPreviousAction() {
+ }
+
+ /* non java doc
+ * @see StructureSelectionAction#internalGetNewSelectionRange(ISourceRange, ICompilationUnit, SelectionAnalyzer)
+ */
+ @Override
+ ISourceRange internalGetNewSelectionRange(ISourceRange oldSourceRange, ISourceReference sr, SelectionAnalyzer selAnalyzer) throws JavaModelException{
+ if (oldSourceRange.getLength() == 0 && selAnalyzer.getLastCoveringNode() != null) {
+ ASTNode previousNode= PreviousNodeAnalyzer.perform(oldSourceRange.getOffset(), selAnalyzer.getLastCoveringNode());
+ if (previousNode != null)
+ return getSelectedNodeSourceRange(sr, previousNode);
+ }
+ ASTNode first= selAnalyzer.getFirstSelectedNode();
+ if (first == null)
+ return getLastCoveringNodeRange(oldSourceRange, sr, selAnalyzer);
+
+ ASTNode parent= first.getParent();
+ if (parent == null)
+ return getLastCoveringNodeRange(oldSourceRange, sr, selAnalyzer);
+
+ ASTNode previousNode= getPreviousNode(parent, selAnalyzer.getSelectedNodes()[0]);
+ if (previousNode == parent)
+ return getSelectedNodeSourceRange(sr, parent);
+
+ int offset= previousNode.getStartPosition();
+ int end= oldSourceRange.getOffset() + oldSourceRange.getLength() - 1;
+ return StructureSelectionAction.createSourceRange(offset, end);
+ }
+
+ private static ASTNode getPreviousNode(ASTNode parent, ASTNode node){
+ ASTNode[] siblingNodes= StructureSelectionAction.getSiblingNodes(node);
+ if (siblingNodes == null || siblingNodes.length == 0)
+ return parent;
+ if (node == siblingNodes[0]) {
+ return parent;
+ } else {
+ int index= StructureSelectionAction.findIndex(siblingNodes, node);
+ if (index < 1)
+ return parent;
+ return siblingNodes[index - 1];
+ }
+ }
+}
+