/* * Copyright (c) 2003-2004 Christopher Lenz and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * Christopher Lenz - initial API and implementation * * $Id: CssDoubleClickStrategy.java,v 1.1 2004-09-02 18:11:48 jsurfer Exp $ */ package net.sourceforge.phpeclipse.css.ui.internal.text; import net.sourceforge.phpeclipse.css.core.internal.text.CssTextUtils; import net.sourceforge.phpeclipse.css.ui.CssUI; import org.eclipse.jface.text.BadLocationException; 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.Region; import org.eclipse.jface.text.source.ICharacterPairMatcher; import org.eclipse.jface.util.Assert; /** * Strategy for selecting CSS identifiers on double click in the editor. * * This strategy implements selection of CSS identifiers on double click inside * an identifier, as well as selection of blocks delimited by square brackets, * curly braces and parenthesis when the user double clicks directly after * either the opening or the closing delimiter. */ public class CssDoubleClickStrategy implements ITextDoubleClickStrategy { // Instance Variables ------------------------------------------------------ /** * The pair matcher used to select ranges delimited by matching pairs of * braces, brackets and parenthesis. */ private ICharacterPairMatcher pairMatcher = new CssPairMatcher(); // ITextDoubleClickStrategy Implementation --------------------------------- /* * @see ITextDoubleClickStrategy#doubleClicked(ITextViewer) */ public void doubleClicked(ITextViewer viewer) { IDocument document = viewer.getDocument(); if (document.getLength() == 0) { return; } int offset = viewer.getSelectedRange().x; Assert.isLegal(offset >= 0, "Double click offset may not be negative"); //$NON-NLS-1$ Assert.isLegal(offset <= document.getLength(), "Double click offset out of range"); //$NON-NLS-1$ IRegion region = pairMatcher.match(document, offset); if ((region != null) && (region.getLength() >= 2)) { viewer.setSelectedRange(region.getOffset() + 1, region.getLength() - 2); } else { try { region = getSurroundingIdentifier(document, offset); if (region != null) { viewer.setSelectedRange( region.getOffset(), region.getLength()); } } catch (BadLocationException e) { CssUI.log("Failed to get surrounding " + //$NON-NLS-1$ "word for double click selection"); //$NON-NLS-1$ } } } // Private Methods --------------------------------------------------------- /** * Returns the region that delimits the identifier surrounding the given * offset into the document. If no identifier is found at the specified * offset, this method returns null. * * @param doc the document * @param offset the zero-based offset into the document * @return the region covered by the identifier, or null if no * identifier was found at that offset */ private IRegion getSurroundingIdentifier(IDocument doc, int offset) throws BadLocationException { IRegion retVal = null; int length = doc.getLength(); offset = Math.min(offset, length - 1); if (CssTextUtils.isCssIdentifierPart(doc.getChar(offset))) { int start = offset; while (start > 0) { if (!CssTextUtils.isCssIdentifierPart(doc.getChar(start - 1))) { break; } start--; } int end = offset; while (end < (length - 1)) { if (!CssTextUtils.isCssIdentifierPart(doc.getChar(end + 1))) { break; } end++; } retVal = new Region(start, end - start + 1); } return retVal; } }