1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-23 08:55:25 +02:00

Fix string double click selection

This commit is contained in:
Anton Leherbauer 2007-04-05 11:15:30 +00:00
parent 32163b8508
commit bf61f08fdb
4 changed files with 142 additions and 216 deletions

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000 2006 IBM Corporation and others.
* Copyright (c) 2000, 2007 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
@ -12,7 +12,6 @@
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextDoubleClickStrategy;
@ -23,111 +22,35 @@ import org.eclipse.jface.text.ITextViewer;
*/
public class CDoubleClickSelector implements ITextDoubleClickStrategy {
protected ITextViewer fText;
protected int fPos;
protected int fStartPos;
protected int fEndPos;
private CPairMatcher fPairMatcher;
protected static char[] fgBrackets= {'{', '}', '(', ')', '[', ']', '"', '"'};
protected static char[] fgBrackets= {'{', '}', '(', ')', '[', ']', '<', '>'};
private CPairMatcher fPairMatcher= new CPairMatcher(fgBrackets);
public CDoubleClickSelector() {
super();
fPairMatcher= new CPairMatcher(fgBrackets);
}
/**
* @see ITextDoubleClickStrategy#doubleClicked
/*
* @see org.eclipse.jface.text.ITextDoubleClickStrategy#doubleClicked(org.eclipse.jface.text.ITextViewer)
*/
public void doubleClicked(ITextViewer text) {
fPos= text.getSelectedRange().x;
public void doubleClicked(ITextViewer textViewer) {
int offset= textViewer.getSelectedRange().x;
if (fPos < 0)
if (offset < 0)
return;
IDocument document= textViewer.getDocument();
fText= text;
if (!selectBracketBlock())
selectWord();
fText= null;
}
protected boolean matchBracketsAt() {
IRegion region= fPairMatcher.match(fText.getDocument(), fPos);
if (region != null && region.getLength() > 0) {
fStartPos= region.getOffset();
fEndPos= fStartPos + region.getLength() - 1;
return true;
}
return false;
}
protected boolean matchWord() {
IDocument doc= fText.getDocument();
try {
int pos= fPos;
char c;
while (pos >= 0) {
c= doc.getChar(pos);
if (!Character.isJavaIdentifierPart(c))
break;
--pos;
}
fStartPos= pos;
pos= fPos;
int length= doc.getLength();
while (pos < length) {
c= doc.getChar(pos);
if (!Character.isJavaIdentifierPart(c))
break;
++pos;
}
fEndPos= pos;
return true;
} catch (BadLocationException x) {
}
return false;
}
protected boolean selectBracketBlock() {
if (matchBracketsAt()) {
if (fStartPos == fEndPos)
fText.setSelectedRange(fStartPos, 0);
else
fText.setSelectedRange(fStartPos + 1, fEndPos - fStartPos - 1);
return true;
}
return false;
}
protected void selectWord() {
if (matchWord()) {
if (fStartPos == fEndPos)
fText.setSelectedRange(fStartPos, 0);
else
fText.setSelectedRange(fStartPos + 1, fEndPos - fStartPos - 1);
IRegion region= fPairMatcher.match(document, offset);
if (region != null && region.getLength() >= 2) {
textViewer.setSelectedRange(region.getOffset() + 1, region.getLength() - 2);
} else {
region= selectWord(document, offset);
textViewer.setSelectedRange(region.getOffset(), region.getLength());
}
}
protected IRegion selectWord(IDocument document, int offset) {
return CWordFinder.findWord(document, offset);
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000 2006 IBM Corporation and others.
* Copyright (c) 2000, 2007 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
@ -12,132 +12,17 @@
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.text.source.ICharacterPairMatcher;
import org.eclipse.jface.text.source.DefaultCharacterPairMatcher;
import org.eclipse.cdt.ui.text.ICPartitions;
/**
* Helper class for match pairs of characters.
*/
public class CPairMatcher implements ICharacterPairMatcher {
protected char[] fPairs;
protected IDocument fDocument;
protected int fOffset;
protected int fStartPos;
protected int fEndPos;
protected int fAnchor;
public class CPairMatcher extends DefaultCharacterPairMatcher {
public CPairMatcher(char[] pairs) {
fPairs = pairs;
super(pairs, ICPartitions.C_PARTITIONING);
}
/*
* @see org.eclipse.jface.text.source.ICharacterPairMatcher#match(org.eclipse.jface.text.IDocument, int)
*/
public IRegion match(IDocument document, int offset) {
fOffset = offset;
if (fOffset < 0)
return null;
fDocument = document;
if (matchPairsAt() && fStartPos != fEndPos)
return new Region(fStartPos, fEndPos - fStartPos + 1);
return null;
}
/*
* @see org.eclipse.jface.text.source.ICharacterPairMatcher#getAnchor()
*/
public int getAnchor() {
return fAnchor;
}
/*
* @see org.eclipse.jface.text.source.ICharacterPairMatcher#clear()
*/
public void clear() {
}
/*
* @see org.eclipse.jface.text.source.ICharacterPairMatcher#dispose()
*/
public void dispose() {
clear();
fDocument = null;
}
protected boolean matchPairsAt() {
int i;
int pairIndex1= fPairs.length;
int pairIndex2= fPairs.length;
fStartPos= -1;
fEndPos= -1;
// get the chars preceding and following the start position
try {
char prevChar= fDocument.getChar(Math.max(fOffset - 1, 0));
// search for opening peer character next to the activation point
for (i= 0; i < fPairs.length; i= i + 2) {
if (prevChar == fPairs[i]) {
fStartPos= fOffset - 1;
pairIndex1= i;
}
}
// search for closing peer character next to the activation point
for (i= 1; i < fPairs.length; i= i + 2) {
if (prevChar == fPairs[i]) {
fEndPos= fOffset - 1;
pairIndex2= i;
}
}
if (fEndPos > -1) {
fAnchor= RIGHT;
fStartPos= searchForOpeningPeer(fEndPos, fPairs[pairIndex2 - 1], fPairs[pairIndex2], fDocument);
if (fStartPos > -1)
return true;
fEndPos= -1;
} else if (fStartPos > -1) {
fAnchor= LEFT;
fEndPos= searchForClosingPeer(fStartPos, fPairs[pairIndex1], fPairs[pairIndex1 + 1], fDocument);
if (fEndPos > -1)
return true;
fStartPos= -1;
}
} catch (BadLocationException x) {
}
return false;
}
protected int searchForClosingPeer(int offset, char openingPeer, char closingPeer, IDocument document) throws BadLocationException {
CHeuristicScanner scanner= new CHeuristicScanner(document, ICPartitions.C_PARTITIONING, TextUtilities.getContentType(document, ICPartitions.C_PARTITIONING, offset, false));
return scanner.findClosingPeer(offset + 1, openingPeer, closingPeer);
}
protected int searchForOpeningPeer(int offset, char openingPeer, char closingPeer, IDocument document) throws BadLocationException {
CHeuristicScanner scanner= new CHeuristicScanner(document, ICPartitions.C_PARTITIONING, TextUtilities.getContentType(document, ICPartitions.C_PARTITIONING, offset, false));
int peer= scanner.findOpeningPeer(offset - 1, openingPeer, closingPeer);
if (peer == CHeuristicScanner.NOT_FOUND)
return -1;
return peer;
}
}

View file

@ -25,6 +25,7 @@ import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.AbstractInformationControlManager;
import org.eclipse.jface.text.DefaultInformationControl;
import org.eclipse.jface.text.DefaultTextDoubleClickStrategy;
import org.eclipse.jface.text.IAutoEditStrategy;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IInformationControl;
@ -451,6 +452,14 @@ public class CSourceViewerConfiguration extends TextSourceViewerConfiguration {
* @see SourceViewerConfiguration#getDoubleClickStrategy(ISourceViewer, String)
*/
public ITextDoubleClickStrategy getDoubleClickStrategy(ISourceViewer sourceViewer, String contentType) {
if (ICPartitions.C_MULTI_LINE_COMMENT.equals(contentType) ||
ICPartitions.C_SINGLE_LINE_COMMENT.equals(contentType))
return new DefaultTextDoubleClickStrategy();
else if (ICPartitions.C_STRING.equals(contentType) ||
ICPartitions.C_CHARACTER.equals(contentType))
return new CStringDoubleClickSelector(getConfiguredDocumentPartitioning(sourceViewer));
else if (ICPartitions.C_PREPROCESSOR.equals(contentType))
return new CStringDoubleClickSelector(getConfiguredDocumentPartitioning(sourceViewer), new CDoubleClickSelector());
return new CDoubleClickSelector();
}

View file

@ -0,0 +1,109 @@
/*******************************************************************************
* Copyright (c) 2007 Wind River Systems, Inc. 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:
* Anton Leherbauer (Wind River Systems) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextDoubleClickStrategy;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.cdt.ui.text.ICPartitions;
import org.eclipse.cdt.internal.ui.editor.CDocumentSetupParticipant;
/**
* Double click strategy aware of string and character syntax rules.
*
* @since 4.0
*/
public class CStringDoubleClickSelector extends CDoubleClickSelector {
private String fPartitioning;
private ITextDoubleClickStrategy fFallbackStrategy;
/**
* Creates a new string double click selector for the given document partitioning.
*
* @param partitioning the document partitioning
*/
public CStringDoubleClickSelector(String partitioning) {
this(partitioning, null);
}
/**
* Creates a new string double click selector for the given document partitioning.
*
* @param partitioning the document partitioning
* @param doubleClickStrategy the fallback double click strategy
*/
public CStringDoubleClickSelector(String partitioning,
ITextDoubleClickStrategy doubleClickStrategy) {
fPartitioning= partitioning;
fFallbackStrategy= doubleClickStrategy;
}
/*
* @see ITextDoubleClickStrategy#doubleClicked(ITextViewer)
*/
public void doubleClicked(ITextViewer textViewer) {
int offset= textViewer.getSelectedRange().x;
if (offset < 0)
return;
IDocument document= textViewer.getDocument();
IRegion region= matchString(document, offset);
if (region != null) {
if (region.getLength() >= 2) {
textViewer.setSelectedRange(region.getOffset() + 1, region.getLength() - 2);
}
} else if (fFallbackStrategy != null) {
fFallbackStrategy.doubleClicked(textViewer);
} else {
region= selectWord(document, offset);
if (region != null) {
textViewer.setSelectedRange(region.getOffset(), region.getLength());
}
}
}
private IRegion matchString(IDocument document, int offset) {
try {
if ((document.getChar(offset) == '"') || (document.getChar(offset) == '\'') ||
(document.getChar(offset - 1) == '"') || (document.getChar(offset - 1) == '\''))
{
ITypedRegion region= TextUtilities.getPartition(document, fPartitioning, offset, true);
// little hack: in case this strategy is used in preprocessor partitions, the string
// partition inside the preprocessor partition must be computed in an extra step
if (ICPartitions.C_PREPROCESSOR.equals(region.getType())) {
String ppDirective= document.get(region.getOffset(), region.getLength());
int hashIdx= ppDirective.indexOf('#');
document= new Document(ppDirective.substring(hashIdx+1));
new CDocumentSetupParticipant().setup(document);
int delta= region.getOffset() + hashIdx + 1;
region= TextUtilities.getPartition(document, fPartitioning, offset - delta, true);
return new Region(region.getOffset() + delta, region.getLength());
}
return region;
}
} catch (BadLocationException e) {
}
return null;
}
}