/*******************************************************************************
* Copyright (c) 2000, 2007 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.aptana.ide.ui.editors.preferences.formatter;
import java.text.ParseException;
import java.util.Map;
import java.util.Vector;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.TextViewer;
import org.eclipse.jface.text.WhitespaceCharacterPainter;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.LineStyleEvent;
import org.eclipse.swt.custom.LineStyleListener;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import com.aptana.ide.core.IdeLog;
import com.aptana.ide.editors.UnifiedEditorsPlugin;
import com.aptana.ide.editors.codeassist.Activator;
import com.aptana.ide.editors.unified.ICodeFormatter;
import com.aptana.ide.editors.unified.LanguageRegistry;
import com.aptana.ide.editors.unified.Messages;
import com.aptana.ide.editors.unified.UnifiedColorizer;
import com.aptana.ide.editors.unified.colorizer.LanguageColorizer;
import com.aptana.ide.lexer.Lexeme;
import com.aptana.ide.lexer.LexemeList;
import com.aptana.ide.lexer.LexerException;
import com.aptana.ide.parsing.IParseState;
import com.aptana.ide.parsing.IParser;
/**
*
*
*/
public abstract class Preview
{
private final class JavaSourcePreviewerUpdater
{
final IPropertyChangeListener fontListener = new IPropertyChangeListener()
{
public void propertyChange(PropertyChangeEvent event)
{
fSourceViewer.getTextWidget().setBackground(languageColorizer.getBackground());
// if (event.getProperty().equals(PreferenceConstants.EDITOR_TEXT_FONT)) {
// final Font font= JFaceResources.getFont(PreferenceConstants.EDITOR_TEXT_FONT);
// fSourceViewer.getTextWidget().setFont(font);
// if (fMarginPainter != null) {
// fMarginPainter.initialize();
// }
// }
}
};
final IPropertyChangeListener propertyListener = new IPropertyChangeListener()
{
public void propertyChange(PropertyChangeEvent event)
{
fSourceViewer.getTextWidget().setBackground(languageColorizer.getBackground());
updateWidget();
}
};
/**
*
*/
public JavaSourcePreviewerUpdater()
{
JFaceResources.getFontRegistry().addListener(fontListener);
fPreferenceStore.addPropertyChangeListener(propertyListener);
fSourceViewer.getTextWidget().addDisposeListener(new DisposeListener()
{
public void widgetDisposed(DisposeEvent e)
{
JFaceResources.getFontRegistry().removeListener(fontListener);
fPreferenceStore.removePropertyChangeListener(propertyListener);
}
});
}
}
/**
*
*/
protected final Document fPreviewDocument;
/**
*
*/
protected IParseState parseState;
/**
*
*/
protected final IParser parser;
/**
*
*/
protected final ICodeFormatter formatter;
/**
*
*/
protected final IPreferenceStore fPreferenceStore;
/**
*
*/
protected TextViewer fSourceViewer;
/**
*
*/
// protected final MarginPainter fMarginPainter;
protected Map fWorkingValues;
private int fTabSize = 0;
private WhitespaceCharacterPainter fWhitespaceCharacterPainter;
private UnifiedColorizer colorizer = UnifiedColorizer.getInstance();
private LanguageColorizer languageColorizer;
/**
* Create a new Java preview
*
* @param workingValues
* @param parent
* @param language
* @param pstore
*/
public Preview(Map workingValues, Composite parent, String language, IPreferenceStore pstore)
{
parser = LanguageRegistry.createParser(language);
formatter = LanguageRegistry.getCodeFormatter(language);
parseState = parser.createParseState(null);
fPreviewDocument = new Document();
fWorkingValues = workingValues;
languageColorizer=LanguageRegistry.getLanguageColorizer(language);
IPreferenceStore prioritizedSettings = UnifiedEditorsPlugin.getDefault().getPreferenceStore();
fPreferenceStore = prioritizedSettings;
fSourceViewer = new TextViewer(parent, SWT.READ_ONLY | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
fSourceViewer.setDocument(fPreviewDocument);
fSourceViewer.getTextWidget().setBackground(languageColorizer.getBackground());
fSourceViewer.getTextWidget().addLineStyleListener(new LineStyleListener()
{
public void lineGetStyle(LineStyleEvent e)
{
{
if (parseState == null)
{
return;
}
LexemeList lexemeList = parseState.getLexemeList();
if (lexemeList == null)
{
IdeLog.logError(UnifiedEditorsPlugin.getDefault(), Messages.UnifiedEditor_LexemeListIsNull);
return;
}
int orgOffset = e.lineOffset;
int offset = orgOffset;
int extra = 0;
int lineLength = e.lineText.length();
int maxLineLength = lineLength;
Lexeme[] lexemes = null;
synchronized (lexemeList)
{
int startingIndex = lexemeList.getLexemeCeilingIndex(offset);
int endingIndex = lexemeList.getLexemeFloorIndex(offset + maxLineLength);
if (startingIndex == -1 && endingIndex != -1)
{
startingIndex = endingIndex;
}
if (endingIndex == -1 && startingIndex != -1)
{
endingIndex = startingIndex;
}
if (startingIndex != -1 && endingIndex != -1)
{
lexemes = lexemeList.cloneRange(startingIndex, endingIndex);
}
}
if (lexemes != null)
{
Vector styles = new Vector();
colorizer.createStyles(parseState, styles, lexemes, true);
StyleRange[] styleResults = (StyleRange[]) styles.toArray(new StyleRange[] {});
// move styles back to actual widget offsets in case of
// folding
if (extra > 0)
{
for (int i = 0; i < styleResults.length; i++)
{
StyleRange range = styleResults[i];
range.start -= extra;
}
}
e.styles = styleResults;
}
}
};
});
// fSourceViewer.configure(fViewerConfiguration);
fSourceViewer.getTextWidget().setFont(JFaceResources.getFont("org.eclipse.jface.textfont")); //$NON-NLS-1$
new JavaSourcePreviewerUpdater();
updateWidget();
}
/**
* @return Control
*/
public Control getControl()
{
return fSourceViewer.getControl();
}
/**
*
*/
public void update()
{
if (fWorkingValues == null)
{
fPreviewDocument.set(""); //$NON-NLS-1$
return;
}
// update the tab size
final int tabSize = getPositiveIntValue((String) fWorkingValues
.get(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE), 0);
if (tabSize != fTabSize)
fSourceViewer.getTextWidget().setTabs(tabSize);
fTabSize = tabSize;
final StyledText widget = (StyledText) fSourceViewer.getControl();
final int height = widget.getClientArea().height;
final int top0 = widget.getTopPixel();
final int totalPixels0 = getHeightOfAllLines(widget);
final int topPixelRange0 = totalPixels0 > height ? totalPixels0 - height : 0;
widget.setRedraw(false);
doFormatPreview();
updateWidget();
fSourceViewer.setSelection(null);
final int totalPixels1 = getHeightOfAllLines(widget);
final int topPixelRange1 = totalPixels1 > height ? totalPixels1 - height : 0;
final int top1 = topPixelRange0 > 0 ? (int) (topPixelRange1 * top0 / (double) topPixelRange0) : 0;
widget.setTopPixel(top1);
widget.setRedraw(true);
updateWidget();
}
/**
*
*/
protected void updateWidget()
{
String string = fSourceViewer.getDocument().get();
parseState = parser.createParseState(null);
parseState.setEditState(string, null, 0, 0);
try
{
parser.parse(parseState);
LexemeList lexemeList = parseState.getLexemeList();
for (int a = 0; a < lexemeList.size(); a++)
{
LanguageRegistry.getLanguageColorizer(lexemeList.get(a).getLanguage());
}
}
catch (ParseException e1)
{
IdeLog.logError(Activator.getDefault(), e1.getMessage());
}
catch (LexerException e1)
{
IdeLog.logError(Activator.getDefault(), e1.getMessage());
}
fSourceViewer.getDocument().set(fSourceViewer.getDocument().get());
}
private int getHeightOfAllLines(StyledText styledText)
{
int height = 0;
int lineCount = styledText.getLineCount();
for (int i = 0; i < lineCount; i++)
height = height + styledText.getLineHeight(styledText.getOffsetAtLine(i));
return height;
}
/**
*
*/
protected abstract void doFormatPreview();
private static int getPositiveIntValue(String string, int defaultValue)
{
try
{
int i = Integer.parseInt(string);
if (i >= 0)
{
return i;
}
}
catch (NumberFormatException e)
{
}
return defaultValue;
}
/**
* @return wValues
*/
public Map getWorkingValues()
{
return fWorkingValues;
}
/**
* @param workingValues
*/
public void setWorkingValues(Map workingValues)
{
fWorkingValues = workingValues;
}
/**
* @param enable
*/
public void showInvisibleCharacters(boolean enable)
{
if (enable)
{
if (fWhitespaceCharacterPainter == null)
{
fWhitespaceCharacterPainter = new WhitespaceCharacterPainter(fSourceViewer);
fSourceViewer.addPainter(fWhitespaceCharacterPainter);
}
}
else
{
if (fWhitespaceCharacterPainter != null)
{
fSourceViewer.removePainter(fWhitespaceCharacterPainter);
fWhitespaceCharacterPainter.deactivate(true);
fWhitespaceCharacterPainter.dispose();
}
fWhitespaceCharacterPainter = null;
}
}
}