/*
* Copyright (c) 2013, the Dart project authors.
*
* Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.dart.tools.ui.internal.text.editor.selectionactions;
import com.google.dart.engine.ast.AstNode;
import com.google.dart.engine.ast.CompilationUnit;
import com.google.dart.engine.ast.visitor.GeneralizingAstVisitor;
import com.google.dart.engine.services.util.SelectionAnalyzer;
import com.google.dart.engine.utilities.source.SourceRange;
import com.google.dart.tools.ui.internal.text.editor.DartEditor;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.text.ITextSelection;
import java.util.ArrayList;
import java.util.List;
public abstract class StructureSelectionAction extends Action {
public static final String NEXT = "SelectNextElement"; //$NON-NLS-1$
public static final String PREVIOUS = "SelectPreviousElement"; //$NON-NLS-1$
public static final String ENCLOSING = "SelectEnclosingElement"; //$NON-NLS-1$
public static final String HISTORY = "RestoreLastSelection"; //$NON-NLS-1$
protected static SourceRange getLastCoveringNodeRange(SourceRange oldSourceRange, AstNode sr,
SelectionAnalyzer selAnalyzer) {
if (selAnalyzer.getCoveringNode() == null) {
return oldSourceRange;
} else {
return getSelectedNodeSourceRange(sr, selAnalyzer.getCoveringNode());
}
}
protected static SourceRange getSelectedNodeSourceRange(AstNode sr, AstNode nodeToSelect) {
int offset = nodeToSelect.getOffset();
int end = Math.min(sr.getLength(), nodeToSelect.getOffset() + nodeToSelect.getLength());
return createSourceRange(offset, end);
}
static SourceRange createSourceRange(int offset, int end) {
int length = end - offset;
if (length == 0) {
length = 1;
}
return new SourceRange(Math.max(0, offset), length);
}
static List<AstNode> getSiblingNodes(AstNode node) {
final List<AstNode> children = new ArrayList<AstNode>();
if (node.getParent() == null) {
children.add(node);
return children;
}
GeneralizingAstVisitor<Void> childVisitor = new GeneralizingAstVisitor<Void>() {
@Override
public Void visitNode(AstNode node) {
children.add(node);
return null;
}
};
node.getParent().visitChildren(childVisitor);
return children;
}
private DartEditor editor;
private SelectionHistory selectionHistory;
/*
* This constructor is for testing purpose only.
*/
protected StructureSelectionAction() {
super(""); //$NON-NLS-1$
}
protected StructureSelectionAction(String text, DartEditor editor, SelectionHistory history) {
super(text);
Assert.isNotNull(editor);
Assert.isNotNull(history);
this.editor = editor;
this.selectionHistory = history;
}
public final SourceRange getNewSelectionRange(SourceRange oldSourceRange, AstNode node) {
CompilationUnit compilationUnit = editor.getInputUnit();
if (compilationUnit == null) {
return oldSourceRange;
}
SelectionAnalyzer selAnalyzer = new SelectionAnalyzer(oldSourceRange);
compilationUnit.accept(selAnalyzer);
return internalGetNewSelectionRange(oldSourceRange, node, selAnalyzer);
}
/*
* Method declared in IAction.
*/
@Override
public final void run() {
CompilationUnit compilationUnit = editor.getInputUnit();
if (compilationUnit == null) {
return;
}
ITextSelection selection = getTextSelection();
SourceRange selectionRange = new SourceRange(selection.getOffset(), selection.getLength());
SourceRange newRange = getNewSelectionRange(selectionRange, compilationUnit);
// Check if new selection differs from current selection
if (selectionRange.equals(newRange)) {
return;
}
selectionHistory.remember(new SourceRange(selection.getOffset(), selection.getLength()));
try {
selectionHistory.ignoreSelectionChanges();
changeSelection(newRange.getOffset(), newRange.getLength());
} finally {
selectionHistory.listenToSelectionChanges();
}
}
protected void changeSelection(int offset, int len) {
editor.selectAndReveal(offset, len);
}
protected final ITextSelection getTextSelection() {
return (ITextSelection) editor.getSelectionProvider().getSelection();
}
/**
* Subclasses determine the actual new selection.
*/
abstract SourceRange internalGetNewSelectionRange(SourceRange oldSourceRange, AstNode node,
SelectionAnalyzer selAnalyzer);
}