blob: 7eeb3fecb3b400751000d24959e7dbd8300facb2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008 Mathias Schaeffner 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:
* Mathias Schaeffner - initial API and implementation
*******************************************************************************/
package org.eclipse.rap.themeeditor.editor.source;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.jface.text.rules.ITokenScanner;
import org.eclipse.jface.text.rules.Token;
import org.eclipse.rap.themeeditor.editor.source.region.IHasParentRegion;
import org.eclipse.rap.themeeditor.editor.source.region.IRegionExt;
import org.eclipse.rap.themeeditor.editor.source.region.SelectorRegion;
/**
* Scans a document and splits its content into tokens, which are implementors
* of IRegionExt.
*/
public class CSSTokenScanner implements ITokenScanner {
private CSSTokenProvider provider;
private CSSSourceEditor editor;
private List outlineRegions;
private List tokenList;
private IRegionExt lastState;
private int currentListPosition;
private int lastListPosition;
private String oldContent;
private int oldListPosition;
private SelectorRegion lastSelector;
public CSSTokenScanner( final CSSSourceEditor editor ) {
this.editor = editor;
provider = new CSSTokenProvider();
tokenList = new ArrayList();
outlineRegions = new ArrayList();
}
public int getTokenLength() {
return lastState.getLength();
}
public int getTokenOffset() {
return lastState.getOffset();
}
public IToken nextToken() {
currentListPosition++;
if( currentListPosition >= tokenList.size()
|| ( currentListPosition > lastListPosition ) )
{
return Token.EOF;
}
lastState = ( IRegionExt )tokenList.get( currentListPosition );
IToken result = provider.createToken( lastState.getTokenType() );
return result;
}
public void setRange( final IDocument document,
final int offset,
final int length )
{
if( document.get().equals( oldContent ) ) {
currentListPosition = oldListPosition;
} else {
oldContent = document.get();
tokenList.clear();
currentListPosition = -1;
lastListPosition = -1;
IRegionExt currentState = new SelectorRegion( -1 );
lastSelector = ( SelectorRegion )currentState;
for( int i = 0; i < document.getLength(); i++ ) {
try {
char character = document.getChar( i );
IRegionExt newState = currentState.getNextState( character );
if( newState != currentState ) {
tokenList.add( currentState );
if( currentState instanceof SelectorRegion ) {
SelectorRegion sr = ( SelectorRegion )currentState;
if( sr.getContent().trim().length() > 0 ) {
lastSelector = ( SelectorRegion )currentState;
}
} else if( currentState instanceof IHasParentRegion ) {
( ( IHasParentRegion )currentState ).setParentRegion( lastSelector );
}
if( ( currentState.getOffset() + currentState.getLength() ) < offset )
{
currentListPosition++;
}
if( currentState.getOffset() < ( offset + length ) ) {
lastListPosition++;
}
currentState = newState;
}
} catch( BadLocationException e ) {
e.printStackTrace();
}
}
tokenList.add( currentState );
if( currentState instanceof SelectorRegion ) {
lastSelector = ( SelectorRegion )currentState;
} else if( currentState instanceof IHasParentRegion ) {
( ( IHasParentRegion )currentState ).setParentRegion( lastSelector );
}
if( ( currentState.getOffset() + currentState.getLength() ) < offset ) {
currentListPosition++;
}
if( currentState.getOffset() < ( offset + length ) ) {
lastListPosition++;
}
oldListPosition = currentListPosition;
}
}
/**
* Returns the token at a given offset position in the document.
*/
public IRegionExt getRegionExt( final int offset ) {
IRegionExt result = null;
Iterator it = tokenList.iterator();
while( it.hasNext() ) {
IRegionExt regionExt = ( IRegionExt )it.next();
if( regionExt.getOffset() <= offset ) {
result = regionExt;
}
}
return result;
}
public List getTokenList() {
return tokenList;
}
/**
* Returns the array of Outline regions that are directly used as the input
* items for the Outline.
*/
public synchronized OutlineRegion[] getOutlineRegionsArray() {
outlineRegions.clear();
boolean bufferEnabled = false;
int offset = 0;
List outlineElements = new ArrayList();
Iterator it = getTokenList().iterator();
while( it.hasNext() ) {
IRegionExt regionExt = ( IRegionExt )it.next();
if( regionExt.getTokenType() == CSSTokenProvider.SELECTOR_TOKEN ) {
outlineElements.add( regionExt );
}
if( regionExt.getTokenType() == CSSTokenProvider.SELECTOR_TOKEN
&& !bufferEnabled )
{
String temp = "";
try {
temp = editor.getDocument().get( regionExt.getOffset(),
regionExt.getLength() ).trim();
} catch( BadLocationException e ) {
temp = "";
}
if( temp.length() > 0 ) {
offset = regionExt.getOffset();
bufferEnabled = true;
}
} else if( regionExt.getTokenType() == CSSTokenProvider.PROPERTY_TOKEN
&& bufferEnabled )
{
bufferEnabled = false;
int length = regionExt.getOffset() - offset - 1;
String content = "";
try {
content = editor.getDocument().get( offset, length ).trim();
} catch( BadLocationException e ) {
e.printStackTrace();
}
if( content.length() > 0 ) {
// ignore comments and white spaces
content = content.replaceAll( "/\\*.*\\*/", " " );
content = content.replaceAll( "\\s+", " " );
OutlineRegion outlineRegion = new OutlineRegion( offset,
length,
content,
outlineElements );
outlineRegions.add( outlineRegion );
outlineElements = new ArrayList();
}
}
}
OutlineRegion[] result = new OutlineRegion[ outlineRegions.size() ];
return ( org.eclipse.rap.themeeditor.editor.source.OutlineRegion[] )outlineRegions.toArray( result );
}
public List getOutlineRegionsList() {
return outlineRegions;
}
}