package tutorial.support;
import java.awt.Color;
import java.awt.Component;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Element;
import javax.swing.text.ParagraphView;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledEditorKit;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
public class CodePanel {
private JTextPane textPane;
private String code;
private static String[] KEYWORDS = {
"private", "protected", "public", "package", "import",
"class", "interface", "extends", "implements", "instanceof", "super", "abstract",
"if", "else", "while", "do", "for", "switch", "case", "return", "new",
"volatile", "transient", "final", "static",
"byte", "short", "char", "int", "long", "float", "double", "boolean", "null", "true", "false", "void",
"try", "catch", "finally", "this"
};
public CodePanel(){
textPane = new JTextPane();
StyledEditorKit editorKit = new StyledEditorKit(){
private ViewFactory factory = new ViewFactory(){
public View create( Element elem ){
View result = getOldViewFactory().create( elem );
if( result instanceof ParagraphView ){
return new ParagraphView( elem ){
public void layout( int width, int height ){
super.layout( Short.MAX_VALUE, height );
}
public float getMinimumSpan( int axis ){
return super.getPreferredSpan( axis );
}
};
}
return result;
}
};
private ViewFactory getOldViewFactory(){
return super.getViewFactory();
}
@Override
public ViewFactory getViewFactory(){
return factory;
}
};
textPane.setEditorKit( editorKit );
textPane.setEditable( false );
}
public Component toComponent(){
return new JScrollPane( textPane );
}
public void copy(){
Clipboard board = Toolkit.getDefaultToolkit().getSystemClipboard();
StringSelection selection = new StringSelection( code );
board.setContents( selection, new ClipboardOwner(){
public void lostOwnership( Clipboard clipboard, Transferable contents ){
// ignore
}
});
}
public void setCode( String code ){
this.code = code;
try{
DefaultStyledDocument document = new DefaultStyledDocument();
Style textStyle = document.addStyle( "text", null );
Style keywordStyle = document.addStyle( "keyword", textStyle );
Style commentStyle = document.addStyle( "comment", textStyle );
Style stringStyle = document.addStyle( "string", textStyle );
StyleConstants.setFontFamily( textStyle, "Monospaced" );
StyleConstants.setBold( textStyle, false );
StyleConstants.setForeground( keywordStyle, new Color( 0, 0, 150 ));
StyleConstants.setBold( keywordStyle, true );
StyleConstants.setForeground( commentStyle, new Color( 0, 150, 0 ));
StyleConstants.setForeground( stringStyle, Color.BLUE );
boolean inString = false;
boolean inMultiLineComment = false;
boolean inSingleLineComment = false;
int blockStart = 0;
int length = code.length();
int documentLength = 0;
for( int i = 0; i < length; i++ ){
if( inString ){
if( code.charAt( i ) == '"' && code.charAt( i-1 ) != '\\' ){
inString = false;
document.insertString( documentLength, code.substring( blockStart, i ), stringStyle );
documentLength = document.getLength();
blockStart = i+1;
}
}
else if( inSingleLineComment ){
if( code.charAt( i ) == '\n' || code.charAt( i ) == '\r' ){
inSingleLineComment = false;
document.insertString( documentLength, code.substring( blockStart, i ), commentStyle );
documentLength = document.getLength();
blockStart = i;
}
}
else if( inMultiLineComment ){
if( code.charAt( i ) == '/' && code.charAt( i-1 ) == '*' ){
inMultiLineComment = false;
document.insertString( documentLength, code.substring( blockStart, i+1 ), commentStyle );
documentLength = document.getLength();
blockStart = i+1;
}
}
else {
char c = code.charAt( i );
if( !Character.isJavaIdentifierPart( c )){
boolean isKeyword = false;
if( i > blockStart ){
String word = code.substring( blockStart, i );
for( String keyword : KEYWORDS ){
if( keyword.equals( word )){
isKeyword = true;
break;
}
}
if( isKeyword ){
if( documentLength < blockStart ){
document.insertString( documentLength, code.substring( documentLength, blockStart ), textStyle );
documentLength = document.getLength();
}
document.insertString( documentLength, word, keywordStyle );
documentLength = document.getLength();
}
}
if( c == '"'){
blockStart = i;
if( documentLength < blockStart ){
document.insertString( documentLength, code.substring( documentLength, blockStart ), textStyle );
documentLength = document.getLength();
}
inString = true;
}
else if( c == '/' ){
blockStart = i;
if( documentLength < blockStart ){
document.insertString( documentLength, code.substring( documentLength, blockStart ), textStyle );
documentLength = document.getLength();
}
if( i+1 < length && code.charAt( i+1 ) == '*' ){
inMultiLineComment = true;
}
else if( i+1 < length && code.charAt( i+1 ) == '/' ){
inSingleLineComment = true;
}
}
else{
blockStart = i+1;
}
}
}
}
if( documentLength < length ){
if( inString ){
document.insertString( documentLength, code.substring( documentLength ), stringStyle );
}
else if( inSingleLineComment || inMultiLineComment ){
document.insertString( documentLength, code.substring( documentLength ), commentStyle );
}
else{
document.insertString( documentLength, code.substring( documentLength ), textStyle );
}
}
textPane.setDocument( document );
}
catch( BadLocationException e ){
e.printStackTrace();
}
}
}