All Downloads are FREE. Search and download functionalities are using the official Maven repository.

editor.BatchDocument Maven / Gradle / Ivy

There is a newer version: 1.18.1
Show newest version
package editor;

import gw.lang.Gosu;
import gw.lang.reflect.IType;
import gw.lang.reflect.TypeSystem;
import gw.lang.reflect.gs.IGosuProgram;

import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Element;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.html.HTML;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;

/**
 * DefaultDocument subclass that supports batching inserts.
 */
public class BatchDocument extends DefaultStyledDocument
{

  public static final char[] EOL_ARRAY = {'\n'};
  private final List _batch = new ArrayList<>();

  public void appendString( String str, AttributeSet a )
  {
    processInserts( getElementsForString( str, a ) );
  }

  public void appendBatchString( String str, AttributeSet a )
  {
    synchronized( _batch )
    {
      _batch.addAll( getElementsForString( str, a ) );
      while( _batch.size() > 100 * 1024 )
      {
        _batch.remove( 0 );
      }
    }
  }

  private List getElementsForString( String str, AttributeSet a )
  {
    if( str.length() > 0 )
    {
      boolean bBytecodeDump = str.startsWith( "// class version " ) && str.contains( "// access flags" );

      List ret = new ArrayList<>();
      SimpleAttributeSet bytecodeDumpColor = new SimpleAttributeSet();
      bytecodeDumpColor.addAttribute( StyleConstants.Foreground, new Color( 92, 225, 92 ) );

      for( StringTokenizer t = new StringTokenizer( str, "\r\n", true ); t.hasMoreTokens(); )
      {
        String s = t.nextToken();
        if( s.equals( "\n" ) )
        {
          ret.addAll( getElementsForLineFeed( a ) );
        }
        else if( bBytecodeDump )
        {
          ret.add( new ElementSpec( bytecodeDumpColor, ElementSpec.ContentType, s.toCharArray(), 0, s.length() ) );
        }
        else
        {
          ret.addAll( _getElementsForString( s, a ) );
        }
      }
      return ret;
    }
    else
    {
      return Collections.emptyList();
    }
  }

  private Collection _getElementsForString( String str, AttributeSet a )
  {
    a = a.copyAttributes();
    char[] chars = str.toCharArray();
    List ret = new ArrayList<>();
    if( !handleStackTraceLink( str, ret, a ) &&
        !handleTestResults( str, ret, a ) )
    {
      ret.add( new ElementSpec( a, ElementSpec.ContentType, chars, 0, str.length() ) );
    }
    return ret;
  }

  private boolean handleStackTraceLink( String str, List ret, AttributeSet a )
  {
    if( str.trim().startsWith( "at " ) && str.contains( "(" ) && str.contains( ".gs" ) && str.contains( ":" ) )
    {
      int iParen = str.indexOf( "(" );
      int iDot = str.indexOf( '.', iParen );
      String name = str.substring( iParen + 1, iDot );
      int iAt = str.indexOf( "at" );
      int iName = str.lastIndexOf( "." + name );
      String fqn = null;
      if( iName >= 0 )
      {
        fqn = str.substring( iAt + 3, iName + name.length() + 1 );
      }
      else
      {
        String rawFqnPlusMethodName = str.substring( iAt + 3, str.indexOf( '(' ) );
        String rawFqn = rawFqnPlusMethodName.substring( 0, rawFqnPlusMethodName.lastIndexOf( '.' ) );
        IType rawType = TypeSystem.getByFullNameIfValid( rawFqn );
        if( rawType instanceof IGosuProgram )
        {
          IType contextType = ((IGosuProgram)rawType).getContextType();
          if( contextType != null )
          {
            fqn = contextType.getName();
          }
        }
        if( fqn == null )
        {
          return false;
        }
      }
      int iLine = str.indexOf( ':' );
      String strLine = "";
      for( int iDigit = iLine + 1; Character.isDigit( str.charAt( iDigit ) ); iDigit++ )
      {
        char c = str.charAt( iDigit );
        strLine += c;
      }
      int line = strLine.length() > 0 ? Integer.parseInt( strLine ) : -1;

      String firstPart = str.substring( 0, iParen + 1 );
      ret.add( new ElementSpec( a, ElementSpec.ContentType, firstPart.toCharArray(), 0, firstPart.length() ) );

      SimpleAttributeSet newAttr = new SimpleAttributeSet();
      newAttr.addAttribute( HTML.Tag.A, new SourceFileAttribute( line, fqn ) );
      newAttr.addAttribute( StyleConstants.Foreground, new Color( 150, 150, 255 ) );
      String link = str.substring( iParen + 1, str.length() - 1 );
      ret.add( new ElementSpec( newAttr, ElementSpec.ContentType, link.toCharArray(), 0, link.length() ) );

      String lastPart = ")";
      ret.add( new ElementSpec( a, ElementSpec.ContentType, lastPart.toCharArray(), 0, 1 ) );
      return true;
    }
    return false;
  }

  private boolean handleTestResults( String str, List ret, AttributeSet a )
  {
    if( str.equals( Gosu.SUCCESS ) )
    {
      SimpleAttributeSet newAttr = new SimpleAttributeSet();
      newAttr.addAttribute( StyleConstants.Foreground, new Color( 90, 220, 90 ) );
      ret.add( new ElementSpec( newAttr, ElementSpec.ContentType, str.toCharArray(), 0, str.length() ) );
      return true;
    }
    else if( str.startsWith( Gosu.FAILED ) && str.contains( " : " ) )
    {
      SimpleAttributeSet newAttr = new SimpleAttributeSet();
      newAttr.addAttribute( StyleConstants.Foreground, new Color( 240, 90, 90 ) );
      ret.add( new ElementSpec( newAttr, ElementSpec.ContentType, Gosu.FAILED.toCharArray(), 0, Gosu.FAILED.length() ) );
      String theRest = str.substring( Gosu.FAILED.length() );
      ret.add( new ElementSpec( a, ElementSpec.ContentType, theRest.toCharArray(), 0, theRest.length() ) );
      return true;
    }
    return false;
  }

  public List getElementsForLineFeed( AttributeSet a )
  {
    List ret = new ArrayList<>( 3 );
    ret.add( new ElementSpec( a, ElementSpec.ContentType, EOL_ARRAY, 0, 1 ) );
    Element paragraph = getParagraphElement( 0 );
    AttributeSet pattr = paragraph.getAttributes();
    ret.add( new ElementSpec( null, ElementSpec.EndTagType ) );
    ret.add( new ElementSpec( pattr, ElementSpec.StartTagType ) );
    return ret;
  }

  public void processBatchUpdates()
  {
    synchronized( _batch )
    {
      processInserts( _batch );
      _batch.clear();
    }
  }

  private void processInserts( List insertsList )
  {
    if( !insertsList.isEmpty() )
    {
      ensureEndStartTagsPrecedeInserts( insertsList );

      ElementSpec[] inserts = new ElementSpec[insertsList.size()];
      insertsList.toArray( inserts );
      try
      {
        super.insert( getLength(), inserts );
      }
      catch( BadLocationException e )
      {
        throw new RuntimeException( e );
      }
    }
  }

  private void ensureEndStartTagsPrecedeInserts( List insertsList )
  {
    Element paragraph = getParagraphElement( 0 );
    AttributeSet pattr = paragraph.getAttributes();
    insertsList.add( 0, new ElementSpec( pattr, ElementSpec.StartTagType ) );
    insertsList.add( 0, new ElementSpec( null, ElementSpec.EndTagType ) );
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy