001: /*******************************************************************************
002: * Copyright (c) 2000, 2005 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.ui.javaeditor.selectionactions;
011:
012: import org.eclipse.jdt.core.ISourceRange;
013: import org.eclipse.jdt.core.ISourceReference;
014: import org.eclipse.jdt.core.JavaModelException;
015: import org.eclipse.jdt.core.dom.ASTNode;
016:
017: import org.eclipse.ui.PlatformUI;
018:
019: import org.eclipse.jdt.internal.corext.dom.GenericVisitor;
020: import org.eclipse.jdt.internal.corext.dom.SelectionAnalyzer;
021:
022: import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
023: import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
024:
025: public class StructureSelectPreviousAction extends
026: StructureSelectionAction {
027:
028: private static class PreviousNodeAnalyzer extends GenericVisitor {
029: private final int fOffset;
030: private ASTNode fPreviousNode;
031:
032: private PreviousNodeAnalyzer(int offset) {
033: super (true);
034: fOffset = offset;
035: }
036:
037: public static ASTNode perform(int offset,
038: ASTNode lastCoveringNode) {
039: PreviousNodeAnalyzer analyzer = new PreviousNodeAnalyzer(
040: offset);
041: lastCoveringNode.accept(analyzer);
042: return analyzer.fPreviousNode;
043: }
044:
045: protected boolean visitNode(ASTNode node) {
046: int start = node.getStartPosition();
047: int end = start + node.getLength();
048: if (end == fOffset) {
049: fPreviousNode = node;
050: return true;
051: } else {
052: return (start < fOffset && fOffset < end);
053: }
054: }
055: }
056:
057: public StructureSelectPreviousAction(JavaEditor editor,
058: SelectionHistory history) {
059: super (SelectionActionMessages.StructureSelectPrevious_label,
060: editor, history);
061: setToolTipText(SelectionActionMessages.StructureSelectPrevious_tooltip);
062: setDescription(SelectionActionMessages.StructureSelectPrevious_description);
063: PlatformUI.getWorkbench().getHelpSystem().setHelp(this ,
064: IJavaHelpContextIds.STRUCTURED_SELECT_PREVIOUS_ACTION);
065: }
066:
067: /*
068: * This constructor is for testing purpose only.
069: */
070: public StructureSelectPreviousAction() {
071: }
072:
073: /* non java doc
074: * @see StructureSelectionAction#internalGetNewSelectionRange(ISourceRange, ICompilationUnit, SelectionAnalyzer)
075: */
076: ISourceRange internalGetNewSelectionRange(
077: ISourceRange oldSourceRange, ISourceReference sr,
078: SelectionAnalyzer selAnalyzer) throws JavaModelException {
079: if (oldSourceRange.getLength() == 0
080: && selAnalyzer.getLastCoveringNode() != null) {
081: ASTNode previousNode = PreviousNodeAnalyzer.perform(
082: oldSourceRange.getOffset(), selAnalyzer
083: .getLastCoveringNode());
084: if (previousNode != null)
085: return getSelectedNodeSourceRange(sr, previousNode);
086: }
087: ASTNode first = selAnalyzer.getFirstSelectedNode();
088: if (first == null)
089: return getLastCoveringNodeRange(oldSourceRange, sr,
090: selAnalyzer);
091:
092: ASTNode parent = first.getParent();
093: if (parent == null)
094: return getLastCoveringNodeRange(oldSourceRange, sr,
095: selAnalyzer);
096:
097: ASTNode previousNode = getPreviousNode(parent, selAnalyzer
098: .getSelectedNodes()[0]);
099: if (previousNode == parent)
100: return getSelectedNodeSourceRange(sr, parent);
101:
102: int offset = previousNode.getStartPosition();
103: int end = oldSourceRange.getOffset()
104: + oldSourceRange.getLength() - 1;
105: return StructureSelectionAction.createSourceRange(offset, end);
106: }
107:
108: private static ASTNode getPreviousNode(ASTNode parent, ASTNode node) {
109: ASTNode[] siblingNodes = StructureSelectionAction
110: .getSiblingNodes(node);
111: if (siblingNodes == null || siblingNodes.length == 0)
112: return parent;
113: if (node == siblingNodes[0]) {
114: return parent;
115: } else {
116: int index = StructureSelectionAction.findIndex(
117: siblingNodes, node);
118: if (index < 1)
119: return parent;
120: return siblingNodes[index - 1];
121: }
122: }
123: }
|