/******************************************************************************* * 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.Arrays; import java.util.List; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.contentassist.CompletionProposal; import org.eclipse.jface.text.contentassist.ContextInformation; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.jface.text.contentassist.IContentAssistProcessor; import org.eclipse.jface.text.contentassist.IContextInformation; import org.eclipse.jface.text.contentassist.IContextInformationValidator; import org.eclipse.rap.themeeditor.SupportedKeywords; import org.eclipse.rap.themeeditor.ThemeEditorPlugin; import org.eclipse.rap.themeeditor.editor.source.region.IRegionExt; import org.eclipse.rwt.internal.theme.ThemeDefElementWrapper; import org.eclipse.rwt.internal.theme.ThemeDefProperty; import org.eclipse.rwt.internal.theme.ThemeDefinitionProvider; public class CSSCompletionProcessor implements IContentAssistProcessor { private CSSTokenScanner tokenScanner; public CSSCompletionProcessor( final CSSTokenScanner tokenScanner ) { this.tokenScanner = tokenScanner; } public ICompletionProposal[] computeCompletionProposals( final ITextViewer viewer, final int offset ) { IRegionExt regionExt = tokenScanner.getRegionExt( offset ); String currentContent = regionExt.getContent(); if( offset >= regionExt.getOffset() && offset <= ( regionExt.getOffset() + regionExt.getLength() ) && ( offset - regionExt.getOffset() ) <= currentContent.length() ) { currentContent = currentContent.substring( 0, offset - regionExt.getOffset() ); } else { return null; } String[] proposalStrings = SupportedKeywords.getKeywordsStartWith( currentContent.trim(), regionExt.getKeywordType() ); if( proposalStrings == null ) { return null; } proposalStrings = filterProposalStrings( proposalStrings, regionExt ); if( proposalStrings.length == 0 ) { return null; } // just a hack to perform trimStart only, as whitespace at end must remain currentContent = currentContent + '#'; int beginIndex = currentContent.trim().length() - 1; ICompletionProposal[] result = new ICompletionProposal[ proposalStrings.length ]; for( int i = 0; i < proposalStrings.length; i++ ) { String additionalInfo = ThemeDefinitionProvider.getDescription( regionExt, proposalStrings[ i ] ); IContextInformation info = new ContextInformation( proposalStrings[ i ], proposalStrings[ i ] ); result[ i ] = new CompletionProposal( proposalStrings[ i ], offset - beginIndex, beginIndex, proposalStrings[ i ].length(), ThemeEditorPlugin.getDefault() .getImage( ThemeEditorPlugin.IMG_FIELD_PRIVATE ), proposalStrings[ i ], info, additionalInfo ); } return result; } public IContextInformation[] computeContextInformation( final ITextViewer viewer, final int offset ) { return null; } public char[] getCompletionProposalAutoActivationCharacters() { return new char[]{ '.', ':', '[' }; } public char[] getContextInformationAutoActivationCharacters() { return null; } public IContextInformationValidator getContextInformationValidator() { return null; } public String getErrorMessage() { return null; } private String[] filterProposalStrings( final String[] proposalStrings, final IRegionExt regionExt ) { String[] result; switch( regionExt.getKeywordType() ) { case SupportedKeywords.STYLE_TYPE: result = filterProposalStyles( proposalStrings, regionExt ); break; case SupportedKeywords.STATE_TYPE: result = filterProposalStates( proposalStrings, regionExt ); break; case SupportedKeywords.PROPERTY_TYPE: result = filterProposalProperties( proposalStrings, regionExt ); break; default: result = proposalStrings; break; } return result; } private String[] filterProposalStyles( final String[] proposalStrings, final IRegionExt regionExt ) { String[] result = new String[ 0 ]; if( regionExt.getTokenType() == CSSTokenProvider.STYLE_TOKEN ) { ThemeDefElementWrapper wrapper = ThemeDefinitionProvider.getElementWrapper( regionExt ); if( wrapper != null ) { List resultList = new ArrayList(); for( int i = 0; i < proposalStrings.length; i++ ) { String text = proposalStrings[ i ]; if( wrapper.element.styleMap.containsKey( text ) ) { resultList.add( text ); } } result = new String[ resultList.size() ]; result = ( String[] )resultList.toArray( result ); } } return result; } private String[] filterProposalStates( final String[] proposalStrings, final IRegionExt regionExt ) { String[] result = new String[ 0 ]; if( regionExt.getTokenType() == CSSTokenProvider.STATE_TOKEN ) { ThemeDefElementWrapper wrapper = ThemeDefinitionProvider.getElementWrapper( regionExt ); if( wrapper != null ) { List resultList = new ArrayList(); for( int i = 0; i < proposalStrings.length; i++ ) { String text = proposalStrings[ i ]; if( wrapper.element.stateMap.containsKey( text ) ) { resultList.add( text ); } } result = new String[ resultList.size() ]; result = ( String[] )resultList.toArray( result ); } } return result; } private String[] filterProposalProperties( final String[] proposalStrings, final IRegionExt regionExt ) { String[] result = new String[ 0 ]; if( regionExt.getTokenType() == CSSTokenProvider.PROPERTY_TOKEN ) { OutlineRegion[] regions = tokenScanner.getOutlineRegionsArray(); OutlineRegion outlineRegion = null; for( int i = 0; i < regions.length; i++ ) { OutlineRegion next = regions[ i ]; if( next.getOffset() <= regionExt.getOffset() ) { outlineRegion = next; } } if( outlineRegion != null ) { List resultList = new ArrayList(); for( int i = 0; i < outlineRegion.getElements().length; i++ ) { ThemeDefElementWrapper wrapper = ThemeDefinitionProvider.getElementWrapper( outlineRegion.getElements()[ i ] ); if( wrapper != null ) { for( int j = 0; j < proposalStrings.length; j++ ) { String text = proposalStrings[ j ]; for( int k = 0; k < wrapper.element.properties.length; k++ ) { ThemeDefProperty property = wrapper.element.properties[ k ]; if( property.name.equals( text ) ) { if( !resultList.contains( text ) ) { resultList.add( text ); } } } } } } result = new String[ resultList.size() ]; result = ( String[] )resultList.toArray( result ); Arrays.sort( result ); } } return result; } }