// Copyright (c) 2003-2008 by Leif Frenzel - see http://leiffrenzel.de // This code is made available under the terms of the Eclipse Public License, // version 1.0 (EPL). See http://www.eclipse.org/legal/epl-v10.html package net.sf.eclipsefp.haskell.ui.internal.editors.haskell.text; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; import net.sf.eclipsefp.haskell.ui.HaskellUIPlugin; import net.sf.eclipsefp.haskell.ui.internal.preferences.editor.IEditorPreferenceNames; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.TextAttribute; import org.eclipse.jface.text.rules.IToken; import org.eclipse.jface.text.rules.Token; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; /** <p>A singleton to manage scanner utilities (like tokens etc.)</p> * * @author Leif Frenzel */ public class ScannerManager implements IEditorPreferenceNames,IPropertyChangeListener { /** The internal singleton reference to ScannerManager */ private static class SingletonHolder { private static final ScannerManager theInstance = new ScannerManager(); } @Deprecated private HaskellCodeScanner codeScanner; @Deprecated private HaskellCommentScanner commentScanner; @Deprecated private HaskellStringScanner stringScanner; @Deprecated private HaskellCharacterScanner charScanner; @Deprecated private HaskellCommentScanner literateCommentScanner; private final Map<String, PropertyChangeHandler> propertyChangeHandlers; //private IPropertyChangeListener propertyChangeListener; private TextAttribute commentAttribute; private TextAttribute literateCommentAttribute; private final Map<String, IToken> tokens = new Hashtable<>(); private IPreferenceStore prefStore=HaskellUIPlugin.getEditorPreferenceStore(); private ColorProvider colorProvider; private ScannerManager() { // prevent instantiation propertyChangeHandlers = new HashMap<>(); initializePropertyListener(); } /** <p>returns the singleton instance of ScannerManager.</p> */ public static final ScannerManager getInstance() { return SingletonHolder.theInstance; } public void dispose() { getPreferenceStore().removePropertyChangeListener( this ); if (colorProvider!=null){ colorProvider.dispose(); } tokens.clear(); } public ScannerManager(final IPreferenceStore prefStore){ this.prefStore=prefStore; propertyChangeHandlers = new HashMap<>(); initializePropertyListener(); } public ColorProvider getColorProvider() { if (prefStore!=null){ if (colorProvider==null){ colorProvider=new ColorProvider( prefStore ); } return colorProvider; } return ColorProvider.getInstance(); } @Deprecated public HaskellCodeScanner getCodeScanner( final boolean latexLiterate ) { if( codeScanner == null ) { codeScanner = new HaskellCodeScanner( this,latexLiterate ); } return codeScanner; } @Deprecated public HaskellCommentScanner getCommentScanner() { if( commentScanner == null ) { commentScanner = new HaskellCommentScanner( this,false ); } return commentScanner; } @Deprecated public HaskellStringScanner getStringScanner() { if( stringScanner == null ) { stringScanner = new HaskellStringScanner(this); } return stringScanner; } @Deprecated public HaskellCharacterScanner getCharacterScanner() { if( charScanner == null ) { charScanner = new HaskellCharacterScanner(this); } return charScanner; } @Deprecated public HaskellCommentScanner getLiterateCommentScanner() { if( literateCommentScanner == null ) { literateCommentScanner = new HaskellCommentScanner( this,true ); } return literateCommentScanner; } public IToken createToken( final String colorKey, final String boldKey ) { IToken result = getTokenInternal( colorKey, boldKey ); if( result == null ) { result = createTokenInternal( colorKey, boldKey ); } return result; } public TextAttribute getCommentAttribute() { if( commentAttribute == null ) { commentAttribute = createTextAttribute( EDITOR_COMMENT_COLOR, EDITOR_COMMENT_BOLD ); } return commentAttribute; } public TextAttribute getLiterateCommentAttribute() { if( literateCommentAttribute == null ) { String colorKey = EDITOR_LITERATE_COMMENT_COLOR; String boldKey = EDITOR_LITERATE_COMMENT_BOLD; literateCommentAttribute = createTextAttribute( colorKey, boldKey ); } return literateCommentAttribute; } // helping methods ////////////////// private TextAttribute createTextAttribute( final String colorKey, final String boldKey ) { Color color = getColorProvider().getColor( colorKey ); TextAttribute result; if( isBold( boldKey ) ) { result = new TextAttribute( color, null, SWT.BOLD ); } else { result = new TextAttribute( color ); } return result; } @Override public void propertyChange( final PropertyChangeEvent event ) { getColorProvider().changeColor( event.getProperty(), event.getNewValue() ); // now notify all tokens out there PropertyChangeHandler handler = getHandler( event.getProperty() ); if( handler != null ) { handler.handleChange( event ); } } private void initializePropertyListener() { getPreferenceStore().addPropertyChangeListener( this ); } private void putHandler( final String key, final PropertyChangeHandler handler ) { propertyChangeHandlers.put( key, handler ); } private PropertyChangeHandler getHandler( final String propertyName ) { Object result = propertyChangeHandlers.get( propertyName ); return ( PropertyChangeHandler )result; } private boolean isBold( final String boldKey ) { return getPreferenceStore().getBoolean( boldKey ); } public IPreferenceStore getPreferenceStore() { if (prefStore!=null){ return prefStore; } return HaskellUIPlugin.getDefault().getPreferenceStore(); } private IToken getTokenInternal( final String colorKey, final String boldKey ) { return tokens.get( colorKey + boldKey ); } private Token createTokenInternal( final String colorKey, final String boldKey ) { TextAttribute textAtt = createTextAttribute( colorKey, boldKey ); final Token result = new Token( textAtt ); PropertyChangeHandler colorHandler = new PropertyChangeHandler() { @Override void handleChange( final PropertyChangeEvent event ) { handleColorChange( result, event.getProperty() ); } }; putHandler( colorKey, colorHandler ); PropertyChangeHandler boldHandler = new PropertyChangeHandler() { @Override void handleChange( final PropertyChangeEvent event ) { handleBoldChange( result, event ); } }; putHandler( boldKey, boldHandler ); tokens.put( colorKey + boldKey, result ); return result; } private void handleColorChange( final Token token, final String key ) { Object data = token.getData(); if( data instanceof TextAttribute ) { TextAttribute oldAttribute = ( TextAttribute )data; Color bgColor = oldAttribute.getBackground(); int style = oldAttribute.getStyle(); Color color = getColorProvider().getColor( key ); TextAttribute newAttribute = new TextAttribute( color, bgColor, style ); token.setData( newAttribute ); } } private void handleBoldChange( final Token token, final PropertyChangeEvent event ) { Object o=event.getNewValue(); boolean bold = (o instanceof Boolean)? ( ( Boolean )o ).booleanValue(): IPreferenceStore.TRUE.equals(o); Object data = token.getData(); if( data instanceof TextAttribute ) { TextAttribute oldAttr = ( TextAttribute )data; boolean wasBold = ( ( oldAttr.getStyle() & SWT.BOLD ) != 0 ); if( wasBold != bold ) { int newStyle = bold ? oldAttr.getStyle() | SWT.BOLD : oldAttr.getStyle() ^ SWT.BOLD; TextAttribute newAttribute = new TextAttribute( oldAttr.getForeground(), oldAttr.getBackground(), newStyle ); token.setData( newAttribute ); } } } // inner classes //////////////// private abstract class PropertyChangeHandler { abstract void handleChange( PropertyChangeEvent event ); } }