// 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.preferences.editor;
import java.io.InputStream;
import net.sf.eclipsefp.haskell.core.util.ResourceUtil;
import net.sf.eclipsefp.haskell.ui.HaskellUIPlugin;
import net.sf.eclipsefp.haskell.ui.internal.editors.haskell.HaskellDocumentProvider;
import net.sf.eclipsefp.haskell.ui.internal.editors.haskell.HaskellSourceViewerConfiguration;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentExtension3;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.text.source.SourceViewerConfiguration;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
/** <p>A source viewer that uses the Haskell editor's presentation helpers
* in order to display a preview of the current presentation preference
* settings.</p>
*
* @author Leif Frenzel
*/
public class SyntaxPreviewer extends SourceViewer implements IEditorPreferenceNames {
private IPreferenceStore store;
private final SourceViewerConfiguration config;
private IPropertyChangeListener propertyChangeListener;
private Color bgColor;
/**
* show the preview content
* @param parent the UI parent
* @param store the preferences store to get color preferences from
*/
SyntaxPreviewer( final Composite parent, final IPreferenceStore store ) {
this(parent,store,new HaskellSourceViewerConfiguration( null ), loadTextFromResource( "preview.hs" ));
}
/**
* show arbitrary content
* @param parent the UI parent
* @param store the preferences store to get color preferences from
* @param config the source viewer configuration
* @param content the document contents
*/
public SyntaxPreviewer( final Composite parent, final IPreferenceStore store,final SourceViewerConfiguration config,final String content ) {
super( parent, null, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER );
this.store = store;
this.config=config;
if (config instanceof HaskellSourceViewerConfiguration){
((HaskellSourceViewerConfiguration)config).setPreferenceStore( store );
}
configure( config );
//done after configure so that the text invalidation is done after the scanner manager being notified
initializePropertyListener();
setEditable( false );
getTextWidget().setFont( JFaceResources.getTextFont() );
IDocument document = new Document( content);
setupDocument( document, IDocumentExtension3.DEFAULT_PARTITIONING );
setDocument( document );
}
@Override
protected void handleDispose() {
if( store != null ) {
if( propertyChangeListener != null ) {
store.removePropertyChangeListener( this.propertyChangeListener );
propertyChangeListener = null;
}
if (config instanceof HaskellSourceViewerConfiguration){
((HaskellSourceViewerConfiguration)config).getScannerManager().dispose();
}
store = null;
}
if( ( this.bgColor != null )
&& !this.bgColor.isDisposed() ) {
this.bgColor.dispose();
}
super.handleDispose();
}
// helping methods
//////////////////
private boolean affectsPresentation( final PropertyChangeEvent event ) {
String p = event.getProperty();
if( EDITOR_BACKGROUND_COLOR.equals( p )
|| EDITOR_BACKGROUND_DEFAULT_COLOR.equals( p ) ) {
return true;
}
for (ColorListEntry cle:SyntaxPP.colorListModel){
if (p.equals(cle.getBoldKey()) || p.equals( cle.getColorKey() )){
return true;
}
}
return false;
}
/** Creates a color from the information stored in the given preference
* store. */
private Color createColor( final String key, final Display display ) {
Color color = null;
if( this.store.contains( key ) ) {
RGB rgb = null;
if( this.store.isDefault( key ) ) {
rgb = PreferenceConverter.getDefaultColor( this.store, key );
} else {
rgb = PreferenceConverter.getColor( this.store, key );
}
if( rgb != null ) {
color = new Color( display, rgb );
}
}
return color;
}
private static String loadTextFromResource( final String name ) {
String result = ""; //$NON-NLS-1$
try (InputStream stream = SyntaxPreviewer.class.getResourceAsStream( name )) {
result = ResourceUtil.readStream( stream );
} catch( Exception ex ) {
HaskellUIPlugin.log( "Could not read preview file.", ex ); //$NON-NLS-1$
}
return result;
}
private void updateColors() {
if( this.store != null ) {
StyledText styledText = getTextWidget();
Color color = null;
if( !this.store.getBoolean( EDITOR_BACKGROUND_DEFAULT_COLOR ) ) {
color = createColor( EDITOR_BACKGROUND_COLOR, styledText.getDisplay() );
}
styledText.setBackground( color );
if( this.bgColor != null ) {
this.bgColor.dispose();
}
this.bgColor = color;
}
}
private void initializePropertyListener() {
propertyChangeListener = new IPropertyChangeListener() {
@Override
public void propertyChange( final PropertyChangeEvent event ) {
if( affectsPresentation( event ) ) {
updateColors();
}
invalidateTextPresentation();
}
};
store.addPropertyChangeListener( this.propertyChangeListener );
}
private void setupDocument( final IDocument document,
final String partitioning ) {
IDocumentPartitioner partitioner = getPartitioner();
if( document instanceof IDocumentExtension3 ) {
IDocumentExtension3 extension = ( IDocumentExtension3 )document;
extension.setDocumentPartitioner( partitioning, partitioner );
} else {
document.setDocumentPartitioner( partitioner );
}
partitioner.connect( document );
}
private IDocumentPartitioner getPartitioner() {
return HaskellDocumentProvider.createDocumentPartitioner();
}
}