001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 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.jface.text;
011:
012: import com.ibm.icu.text.BreakIterator;
013: import java.text.CharacterIterator;
014:
015: /**
016: * Standard implementation of
017: * {@link org.eclipse.jface.text.ITextDoubleClickStrategy}.
018: * <p>
019: * Selects words using <code>java.text.BreakIterator</code> for the default
020: * locale.</p>
021: * <p>
022: * This class is not intended to be subclassed.
023: * </p>
024: *
025: * @see java.text.BreakIterator
026: */
027: public class DefaultTextDoubleClickStrategy implements
028: ITextDoubleClickStrategy {
029:
030: /**
031: * Implements a character iterator that works directly on
032: * instances of <code>IDocument</code>. Used to collaborate with
033: * the break iterator.
034: *
035: * @see IDocument
036: * @since 2.0
037: */
038: static class DocumentCharacterIterator implements CharacterIterator {
039:
040: /** Document to iterate over. */
041: private IDocument fDocument;
042: /** Start offset of iteration. */
043: private int fOffset = -1;
044: /** End offset of iteration. */
045: private int fEndOffset = -1;
046: /** Current offset of iteration. */
047: private int fIndex = -1;
048:
049: /** Creates a new document iterator. */
050: public DocumentCharacterIterator() {
051: }
052:
053: /**
054: * Configures this document iterator with the document section to be visited.
055: *
056: * @param document the document to be iterated
057: * @param iteratorRange the range in the document to be iterated
058: */
059: public void setDocument(IDocument document,
060: IRegion iteratorRange) {
061: fDocument = document;
062: fOffset = iteratorRange.getOffset();
063: fEndOffset = fOffset + iteratorRange.getLength();
064: }
065:
066: /*
067: * @see CharacterIterator#first()
068: */
069: public char first() {
070: fIndex = fOffset;
071: return current();
072: }
073:
074: /*
075: * @see CharacterIterator#last()
076: */
077: public char last() {
078: fIndex = fOffset < fEndOffset ? fEndOffset - 1 : fEndOffset;
079: return current();
080: }
081:
082: /*
083: * @see CharacterIterator#current()
084: */
085: public char current() {
086: if (fOffset <= fIndex && fIndex < fEndOffset) {
087: try {
088: return fDocument.getChar(fIndex);
089: } catch (BadLocationException x) {
090: }
091: }
092: return DONE;
093: }
094:
095: /*
096: * @see CharacterIterator#next()
097: */
098: public char next() {
099: ++fIndex;
100: int end = getEndIndex();
101: if (fIndex >= end) {
102: fIndex = end;
103: return DONE;
104: }
105: return current();
106: }
107:
108: /*
109: * @see CharacterIterator#previous()
110: */
111: public char previous() {
112: if (fIndex == fOffset)
113: return DONE;
114:
115: if (fIndex > fOffset)
116: --fIndex;
117:
118: return current();
119: }
120:
121: /*
122: * @see CharacterIterator#setIndex(int)
123: */
124: public char setIndex(int index) {
125: fIndex = index;
126: return current();
127: }
128:
129: /*
130: * @see CharacterIterator#getBeginIndex()
131: */
132: public int getBeginIndex() {
133: return fOffset;
134: }
135:
136: /*
137: * @see CharacterIterator#getEndIndex()
138: */
139: public int getEndIndex() {
140: return fEndOffset;
141: }
142:
143: /*
144: * @see CharacterIterator#getIndex()
145: */
146: public int getIndex() {
147: return fIndex;
148: }
149:
150: /*
151: * @see CharacterIterator#clone()
152: */
153: public Object clone() {
154: DocumentCharacterIterator i = new DocumentCharacterIterator();
155: i.fDocument = fDocument;
156: i.fIndex = fIndex;
157: i.fOffset = fOffset;
158: i.fEndOffset = fEndOffset;
159: return i;
160: }
161: }
162:
163: /**
164: * The document character iterator used by this strategy.
165: * @since 2.0
166: */
167: private DocumentCharacterIterator fDocIter = new DocumentCharacterIterator();
168:
169: /**
170: * Creates a new default text double click strategy.
171: */
172: public DefaultTextDoubleClickStrategy() {
173: super ();
174: }
175:
176: /*
177: * @see org.eclipse.jface.text.ITextDoubleClickStrategy#doubleClicked(org.eclipse.jface.text.ITextViewer)
178: */
179: public void doubleClicked(ITextViewer text) {
180:
181: int position = text.getSelectedRange().x;
182:
183: if (position < 0)
184: return;
185:
186: try {
187:
188: IDocument document = text.getDocument();
189: IRegion line = document
190: .getLineInformationOfOffset(position);
191: if (position == line.getOffset() + line.getLength())
192: return;
193:
194: fDocIter.setDocument(document, line);
195:
196: BreakIterator breakIter = BreakIterator.getWordInstance();
197: breakIter.setText(fDocIter);
198:
199: int start = breakIter.preceding(position);
200: if (start == BreakIterator.DONE)
201: start = line.getOffset();
202:
203: int end = breakIter.following(position);
204: if (end == BreakIterator.DONE)
205: end = line.getOffset() + line.getLength();
206:
207: if (breakIter.isBoundary(position)) {
208: if (end - position > position - start)
209: start = position;
210: else
211: end = position;
212: }
213:
214: if (start != end)
215: text.setSelectedRange(start, end - start);
216:
217: } catch (BadLocationException x) {
218: }
219: }
220: }
|