/******************************************************************************* * Copyright (c) 2000, 2015 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 * Bruno Medeiros - copied from org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.gotoMatchingBracket() *******************************************************************************/ package melnorme.lang.ide.ui.editor.actions; import java.util.ArrayList; import java.util.List; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.ITextViewerExtension5; import org.eclipse.jface.text.Region; import org.eclipse.jface.text.source.ICharacterPairMatcher; import melnorme.lang.ide.ui.editor.AbstractLangEditor; import melnorme.lang.ide.ui.editor.EditorUtils; import melnorme.lang.ide.ui.editor.LangEditorMessages; import melnorme.lang.ide.ui.editor.text.LangPairMatcher; import melnorme.utilbox.ownership.IDisposable; public class GotoMatchingBracketManager implements IDisposable { protected final AbstractLangEditor langEditor; /** * Previous location history for goto matching bracket action. * * @since 3.8 */ private List<IRegion> fPreviousSelections; public GotoMatchingBracketManager(AbstractLangEditor abstractLangEditor) { this.langEditor = abstractLangEditor; } protected LangPairMatcher getBracketMatcher() { return langEditor.getBracketMatcher(); } protected void initializePreviousSelectionList() { fPreviousSelections= new ArrayList<IRegion>(3); } @Override public void dispose() { fPreviousSelections.clear(); } public void gotoMatchingBracket() { ITextViewer sourceViewer = langEditor.getSourceViewer_(); IDocument document= sourceViewer.getDocument(); if (document == null) return; IRegion selection= EditorUtils.getSignedSelection(sourceViewer); if (fPreviousSelections == null) initializePreviousSelectionList(); IRegion region= getBracketMatcher().match(document, selection.getOffset(), selection.getLength()); if (region == null) { region= getBracketMatcher().findEnclosingPeerCharacters(document, selection.getOffset(), selection.getLength()); initializePreviousSelectionList(); fPreviousSelections.add(selection); } else { if (fPreviousSelections.size() == 2) { if (!selection.equals(fPreviousSelections.get(1))) { initializePreviousSelectionList(); } } else if (fPreviousSelections.size() == 3) { if (selection.equals(fPreviousSelections.get(2)) && !selection.equals(fPreviousSelections.get(0))) { IRegion originalSelection= fPreviousSelections.get(0); sourceViewer.setSelectedRange(originalSelection.getOffset(), originalSelection.getLength()); sourceViewer.revealRange(originalSelection.getOffset(), originalSelection.getLength()); initializePreviousSelectionList(); return; } initializePreviousSelectionList(); } } if (region == null) { langEditor.setStatusLineErrorMessage(LangEditorMessages.GotoMatchingBracket_error_noMatchingBracket); sourceViewer.getTextWidget().getDisplay().beep(); return; } int offset= region.getOffset(); int length= region.getLength(); if (length < 1) return; int anchor= getBracketMatcher().getAnchor(); // http://dev.eclipse.org/bugs/show_bug.cgi?id=34195 int targetOffset= (ICharacterPairMatcher.RIGHT == anchor) ? offset + 1 : offset + length - 1; boolean visible= false; if (sourceViewer instanceof ITextViewerExtension5) { ITextViewerExtension5 extension= (ITextViewerExtension5) sourceViewer; visible= (extension.modelOffset2WidgetOffset(targetOffset) > -1); } else { IRegion visibleRegion= sourceViewer.getVisibleRegion(); // http://dev.eclipse.org/bugs/show_bug.cgi?id=34195 visible= (targetOffset >= visibleRegion.getOffset() && targetOffset <= visibleRegion.getOffset() + visibleRegion.getLength()); } if (!visible) { langEditor.setStatusLineErrorMessage(LangEditorMessages.GotoMatchingBracket_error_bracketOutsideSelectedElement); sourceViewer.getTextWidget().getDisplay().beep(); return; } int adjustment= getBracketMatcher().getOffsetAdjustment(document, selection.getOffset() + selection.getLength(), selection.getLength()); targetOffset+= adjustment; int direction= (selection.getLength() == 0) ? 0 : ((selection.getLength() > 0) ? 1 : -1); if (fPreviousSelections.size() == 1 && direction < 0) { targetOffset++; } if (fPreviousSelections.size() > 0) { fPreviousSelections.add(new Region(targetOffset, direction)); } sourceViewer.setSelectedRange(targetOffset, direction); sourceViewer.revealRange(targetOffset, direction); } }