intial source from ttp://www.sf.net/projects/wdte
[phpeclipse.git] / archive / net.sourceforge.phpeclipse.css.ui / src / net / sourceforge / phpeclipse / css / ui / internal / text / CssDoubleClickStrategy.java
1 /*
2  * Copyright (c) 2003-2004 Christopher Lenz and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     Christopher Lenz - initial API and implementation
10  * 
11  * $Id: CssDoubleClickStrategy.java,v 1.1 2004-09-02 18:11:48 jsurfer Exp $
12  */
13
14 package net.sourceforge.phpeclipse.css.ui.internal.text;
15
16 import net.sourceforge.phpeclipse.css.core.internal.text.CssTextUtils;
17 import net.sourceforge.phpeclipse.css.ui.CssUI;
18
19 import org.eclipse.jface.text.BadLocationException;
20 import org.eclipse.jface.text.IDocument;
21 import org.eclipse.jface.text.IRegion;
22 import org.eclipse.jface.text.ITextDoubleClickStrategy;
23 import org.eclipse.jface.text.ITextViewer;
24 import org.eclipse.jface.text.Region;
25 import org.eclipse.jface.text.source.ICharacterPairMatcher;
26 import org.eclipse.jface.util.Assert;
27
28 /**
29  * Strategy for selecting CSS identifiers on double click in the editor.
30  * 
31  * This strategy implements selection of CSS identifiers on double click inside
32  * an identifier, as well as selection of blocks delimited by square brackets,
33  * curly braces and parenthesis when the user double clicks directly after
34  * either the opening or the closing delimiter.
35  */
36 public class CssDoubleClickStrategy implements ITextDoubleClickStrategy {
37
38         // Instance Variables ------------------------------------------------------
39
40         /**
41          * The pair matcher used to select ranges delimited by matching pairs of
42          * braces, brackets and parenthesis.
43          */
44         private ICharacterPairMatcher pairMatcher = new CssPairMatcher();
45
46         // ITextDoubleClickStrategy Implementation ---------------------------------
47
48         /*
49          * @see ITextDoubleClickStrategy#doubleClicked(ITextViewer)
50          */
51         public void doubleClicked(ITextViewer viewer) {
52                 IDocument document = viewer.getDocument();
53                 if (document.getLength() == 0) {
54                         return;   
55                 }
56                 int offset = viewer.getSelectedRange().x;
57                 Assert.isLegal(offset >= 0,
58                         "Double click offset may not be negative"); //$NON-NLS-1$
59                 Assert.isLegal(offset <= document.getLength(),
60                         "Double click offset out of range"); //$NON-NLS-1$
61                 IRegion region = pairMatcher.match(document, offset);
62                 if ((region != null) && (region.getLength() >= 2)) {
63                         viewer.setSelectedRange(region.getOffset() + 1,
64                                 region.getLength() - 2);
65                 } else {
66                         try {
67                                 region = getSurroundingIdentifier(document, offset);
68                                 if (region != null) {
69                                         viewer.setSelectedRange(
70                                                 region.getOffset(), region.getLength());
71                                 }
72                         } catch (BadLocationException e) {
73                                 CssUI.log("Failed to get surrounding " + //$NON-NLS-1$
74                                         "word for double click selection"); //$NON-NLS-1$
75                         }
76                 }
77         }
78
79         // Private Methods ---------------------------------------------------------
80
81         /**
82          * Returns the region that delimits the identifier surrounding the given
83          * offset into the document. If no identifier is found at the specified
84          * offset, this method returns <code>null</code>.
85          * 
86          * @param doc the document
87          * @param offset the zero-based offset into the document
88          * @return the region covered by the identifier, or <code>null</code> if no
89          *         identifier was found at that offset
90          */
91         private IRegion getSurroundingIdentifier(IDocument doc, int offset)
92                 throws BadLocationException {
93                 IRegion retVal = null;
94                 int length = doc.getLength();
95                 offset = Math.min(offset, length - 1);
96                 if (CssTextUtils.isCssIdentifierPart(doc.getChar(offset))) {
97                         int start = offset;
98                         while (start > 0) {
99                                 if (!CssTextUtils.isCssIdentifierPart(doc.getChar(start - 1))) {
100                                         break;
101                                 }
102                                 start--;
103                         }
104                         int end = offset;
105                         while (end < (length - 1)) {
106                                 if (!CssTextUtils.isCssIdentifierPart(doc.getChar(end + 1))) {
107                                         break;
108                                 }
109                                 end++;
110                         }
111                         retVal = new Region(start, end - start + 1);
112                 }
113                 return retVal;
114         }
115
116 }