Package org.syntax.jedit

Source Code of org.syntax.jedit.TextAreaPainter$Highlight

/*
*  soapUI, copyright (C) 2004-2011 eviware.com
*
*  soapUI is free software; you can redistribute it and/or modify it under the
*  terms of version 2.1 of the GNU Lesser General Public License as published by
*  the Free Software Foundation.
*
*  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
*  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*  See the GNU Lesser General Public License for more details at gnu.org.
*/

package org.syntax.jedit;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;

import javax.swing.JComponent;
import javax.swing.ToolTipManager;
import javax.swing.text.PlainDocument;
import javax.swing.text.Segment;
import javax.swing.text.TabExpander;
import javax.swing.text.Utilities;

import org.syntax.jedit.tokenmarker.Token;
import org.syntax.jedit.tokenmarker.TokenMarker;

import com.eviware.soapui.SoapUI;

/**
* The text area repaint manager. It performs double buffering and paints lines
* of text.
*
* @author Slava Pestov
* @version $Id$
*/
public class TextAreaPainter extends JComponent implements TabExpander
{
  private int areaWidth;
  private int areaHeight;

  /**
   * Creates a new repaint manager. This should be not be called directly.
   */
  public TextAreaPainter( JEditTextArea textArea, TextAreaDefaults defaults )
  {
    this.textArea = textArea;

    setAutoscrolls( true );
    setDoubleBuffered( true );
    setOpaque( true );
    setBorder( null );

    ToolTipManager.sharedInstance().registerComponent( this );

    currentLine = new Segment();
    currentLineIndex = -1;

    setCursor( Cursor.getPredefinedCursor( Cursor.TEXT_CURSOR ) );

    setFont( new Font( "Monospaced", Font.PLAIN, 14 ) );
    setForeground( Color.black );
    setBackground( Color.white );

    blockCaret = defaults.blockCaret;
    styles = defaults.styles;
    // cols = defaults.cols;
    // rows = defaults.rows;
    caretColor = defaults.caretColor;
    selectionColor = defaults.selectionColor;
    lineHighlightColor = defaults.lineHighlightColor;
    lineHighlight = defaults.lineHighlight;
    bracketHighlightColor = defaults.bracketHighlightColor;
    bracketHighlight = defaults.bracketHighlight;
    paintInvalid = defaults.paintInvalid;
    eolMarkerColor = defaults.eolMarkerColor;
    eolMarkers = defaults.eolMarkers;
  }

  /**
   * Returns if this component can be traversed by pressing the Tab key. This
   * returns false.
   */
  public final boolean isManagingFocus()
  {
    return false;
  }

  /**
   * Returns the syntax styles used to paint colorized text. Entry <i>n</i>
   * will be used to paint tokens with id = <i>n</i>.
   *
   * @see org.syntax.jedit.Token
   */
  public final SyntaxStyle[] getStyles()
  {
    return styles;
  }

  /**
   * Sets the syntax styles used to paint colorized text. Entry <i>n</i> will
   * be used to paint tokens with id = <i>n</i>.
   *
   * @param styles
   *           The syntax styles
   * @see org.syntax.jedit.Token
   */
  public final void setStyles( SyntaxStyle[] styles )
  {
    this.styles = styles;
    repaint();
  }

  /**
   * Returns the caret color.
   */
  public final Color getCaretColor()
  {
    return caretColor;
  }

  /**
   * Sets the caret color.
   *
   * @param caretColor
   *           The caret color
   */
  public final void setCaretColor( Color caretColor )
  {
    this.caretColor = caretColor;
    invalidateSelectedLines();
  }

  /**
   * Returns the selection color.
   */
  public final Color getSelectionColor()
  {
    return selectionColor;
  }

  /**
   * Sets the selection color.
   *
   * @param selectionColor
   *           The selection color
   */
  public final void setSelectionColor( Color selectionColor )
  {
    this.selectionColor = selectionColor;
    invalidateSelectedLines();
  }

  /**
   * Returns the line highlight color.
   */
  public final Color getLineHighlightColor()
  {
    return lineHighlightColor;
  }

  /**
   * Sets the line highlight color.
   *
   * @param lineHighlightColor
   *           The line highlight color
   */
  public final void setLineHighlightColor( Color lineHighlightColor )
  {
    this.lineHighlightColor = lineHighlightColor;
    invalidateSelectedLines();
  }

  /**
   * Returns true if line highlight is enabled, false otherwise.
   */
  public final boolean isLineHighlightEnabled()
  {
    return lineHighlight;
  }

  /**
   * Enables or disables current line highlighting.
   *
   * @param lineHighlight
   *           True if current line highlight should be enabled, false
   *           otherwise
   */
  public final void setLineHighlightEnabled( boolean lineHighlight )
  {
    this.lineHighlight = lineHighlight;
    invalidateSelectedLines();
  }

  /**
   * Returns the bracket highlight color.
   */
  public final Color getBracketHighlightColor()
  {
    return bracketHighlightColor;
  }

  /**
   * Sets the bracket highlight color.
   *
   * @param bracketHighlightColor
   *           The bracket highlight color
   */
  public final void setBracketHighlightColor( Color bracketHighlightColor )
  {
    this.bracketHighlightColor = bracketHighlightColor;
    invalidateLine( textArea.getBracketLine() );
  }

  /**
   * Returns true if bracket highlighting is enabled, false otherwise. When
   * bracket highlighting is enabled, the bracket matching the one before the
   * caret (if any) is highlighted.
   */
  public final boolean isBracketHighlightEnabled()
  {
    return bracketHighlight;
  }

  /**
   * Enables or disables bracket highlighting. When bracket highlighting is
   * enabled, the bracket matching the one before the caret (if any) is
   * highlighted.
   *
   * @param bracketHighlight
   *           True if bracket highlighting should be enabled, false otherwise
   */
  public final void setBracketHighlightEnabled( boolean bracketHighlight )
  {
    this.bracketHighlight = bracketHighlight;
    invalidateLine( textArea.getBracketLine() );
  }

  /**
   * Returns true if the caret should be drawn as a block, false otherwise.
   */
  public final boolean isBlockCaretEnabled()
  {
    return blockCaret;
  }

  /**
   * Sets if the caret should be drawn as a block, false otherwise.
   *
   * @param blockCaret
   *           True if the caret should be drawn as a block, false otherwise.
   */
  public final void setBlockCaretEnabled( boolean blockCaret )
  {
    this.blockCaret = blockCaret;
    invalidateSelectedLines();
  }

  /**
   * Returns the EOL marker color.
   */
  public final Color getEOLMarkerColor()
  {
    return eolMarkerColor;
  }

  /**
   * Sets the EOL marker color.
   *
   * @param eolMarkerColor
   *           The EOL marker color
   */
  public final void setEOLMarkerColor( Color eolMarkerColor )
  {
    this.eolMarkerColor = eolMarkerColor;
    repaint();
  }

  /**
   * Returns true if EOL markers are drawn, false otherwise.
   */
  public final boolean getEOLMarkersPainted()
  {
    return eolMarkers;
  }

  /**
   * Sets if EOL markers are to be drawn.
   *
   * @param eolMarkers
   *           True if EOL markers should be drawn, false otherwise
   */
  public final void setEOLMarkersPainted( boolean eolMarkers )
  {
    this.eolMarkers = eolMarkers;
    repaint();
  }

  /**
   * Returns true if invalid lines are painted as red tildes (~), false
   * otherwise.
   */
  public boolean getInvalidLinesPainted()
  {
    return paintInvalid;
  }

  /**
   * Sets if invalid lines are to be painted as red tildes.
   *
   * @param paintInvalid
   *           True if invalid lines should be drawn, false otherwise
   */
  public void setInvalidLinesPainted( boolean paintInvalid )
  {
    this.paintInvalid = paintInvalid;
  }

  /**
   * Adds a custom highlight painter.
   *
   * @param highlight
   *           The highlight
   */
  public void addCustomHighlight( Highlight highlight )
  {
    highlight.init( textArea, highlights );
    highlights = highlight;
  }

  /**
   * Highlight interface.
   */
  public interface Highlight
  {
    /**
     * Called after the highlight painter has been added.
     *
     * @param textArea
     *           The text area
     * @param next
     *           The painter this one should delegate to
     */
    void init( JEditTextArea textArea, Highlight next );

    /**
     * This should paint the highlight and delgate to the next highlight
     * painter.
     *
     * @param gfx
     *           The graphics context
     * @param line
     *           The line number
     * @param y
     *           The y co-ordinate of the line
     */
    void paintHighlight( Graphics gfx, int line, int y );

    /**
     * Returns the tool tip to display at the specified location. If this
     * highlighter doesn't know what to display, it should delegate to the
     * next highlight painter.
     *
     * @param evt
     *           The mouse event
     */
    String getToolTipText( MouseEvent evt );
  }

  /**
   * Returns the tool tip to display at the specified location.
   *
   * @param evt
   *           The mouse event
   */
  public String getToolTipText( MouseEvent evt )
  {
    if( highlights != null )
      return highlights.getToolTipText( evt );
    else
      return null;
  }

  /**
   * Returns the font metrics used by this component.
   */
  public FontMetrics getFontMetrics()
  {
    return fm;
  }

  /**
   * Sets the font for this component. This is overridden to update the cached
   * font metrics and to recalculate which lines are visible.
   *
   * @param font
   *           The font
   */
  public void setFont( Font font )
  {
    super.setFont( font );
    fm = Toolkit.getDefaultToolkit().getFontMetrics( font );
    textArea.recalculateVisibleLines();
  }

  /**
   * Repaints the text.
   *
   * @param g
   *           The graphics context
   */
  public void paint( Graphics gfx )
  {
    Rectangle clipRect = gfx.getClipBounds();

    gfx.setColor( getBackground() );
    gfx.fillRect( clipRect.x, clipRect.y, clipRect.width, clipRect.height );

    // We don't use yToLine() here because that method doesn't
    // return lines past the end of the document
    int height = fm.getHeight();
    int firstLine = textArea.getFirstLine();
    int firstInvalid = firstLine + clipRect.y / height;
    // Because the clipRect's height is usually an even multiple
    // of the font height, we subtract 1 from it, otherwise one
    // too many lines will always be painted.
    int lastInvalid = firstLine + ( clipRect.y + clipRect.height - 1 ) / height;

    try
    {
      TokenMarker tokenMarker = textArea.getDocument().getTokenMarker();
      int x = 0; // -textArea.getHorizontalOffset();

      for( int line = firstInvalid; line <= lastInvalid; line++ )
      {
        paintLine( gfx, tokenMarker, line, x );
      }

      if( tokenMarker != null && tokenMarker.isNextLineRequested() )
      {
        int h = clipRect.y + clipRect.height;
        repaint( 0, h, getWidth(), getHeight() - h );
      }
    }
    catch( Exception e )
    {
      System.err.println( "Error repainting line" + " range {" + firstInvalid + "," + lastInvalid + "}:" );
      SoapUI.logError( e );
    }
  }

  /**
   * Marks a line as needing a repaint.
   *
   * @param line
   *           The line to invalidate
   */
  public final void invalidateLine( int line )
  {
    repaint( 0, textArea.lineToY( line ) + fm.getMaxDescent() + fm.getLeading(), getWidth(), fm.getHeight() );
  }

  /**
   * Marks a range of lines as needing a repaint.
   *
   * @param firstLine
   *           The first line to invalidate
   * @param lastLine
   *           The last line to invalidate
   */
  public final void invalidateLineRange( int firstLine, int lastLine )
  {
    repaint( 0, textArea.lineToY( firstLine ) + fm.getMaxDescent() + fm.getLeading(), getWidth(), ( lastLine
        - firstLine + 1 )
        * fm.getHeight() );
  }

  /**
   * Repaints the lines containing the selection.
   */
  public final void invalidateSelectedLines()
  {
    invalidateLineRange( textArea.getSelectionStartLine(), textArea.getSelectionEndLine() );
  }

  /**
   * Implementation of TabExpander interface. Returns next tab stop after a
   * specified point.
   *
   * @param x
   *           The x co-ordinate
   * @param tabOffset
   *           Ignored
   * @return The next tab stop after <i>x</i>
   */
  public float nextTabStop( float x, int tabOffset )
  {
    if( tabSize == 0 )
      initTabSize();

    int offset = 0; // -textArea.getHorizontalOffset();
    int ntabs = ( ( int )x - offset ) / tabSize;
    return ( ntabs + 1 ) * tabSize + offset;
  }

  private void initTabSize()
  {
    tabSize = fm.charWidth( ' ' )
        * ( ( Integer )textArea.getDocument().getProperty( PlainDocument.tabSizeAttribute ) ).intValue();
    if( tabSize == 0 )
      tabSize = fm.charWidth( ' ' ) * 4;
  }

  /**
   * Returns the painter's preferred size.
   */
  public Dimension getPreferredSize()
  {
    Dimension dim = new Dimension();
    dim.width = fm.charWidth( 'w' ) * textArea.getMaxLineLength() + 5;
    dim.height = fm.getHeight() * textArea.getLineCount() + 5;
    return dim;
  }

  /**
   * Returns the painter's minimum size.
   */
  public Dimension getMinimumSize()
  {
    return getPreferredSize();
  }

  public Dimension getMaximumSize()
  {
    return getPreferredSize();
  }

  // package-private members
  int currentLineIndex;
  Token currentLineTokens;
  Segment currentLine;

  // protected members
  protected JEditTextArea textArea;

  protected SyntaxStyle[] styles;
  protected Color caretColor;
  protected Color selectionColor;
  protected Color lineHighlightColor;
  protected Color bracketHighlightColor;
  protected Color eolMarkerColor;

  protected boolean blockCaret;
  protected boolean lineHighlight;
  protected boolean bracketHighlight;
  protected boolean paintInvalid;
  protected boolean eolMarkers;
  // protected int cols;
  // protected int rows;

  protected int tabSize;
  protected FontMetrics fm;

  protected Highlight highlights;

  protected void paintLine( Graphics gfx, TokenMarker tokenMarker, int line, int x )
  {
    Font defaultFont = getFont();
    Color defaultColor = getForeground();

    currentLineIndex = line;
    int y = textArea.lineToY( line );

    int lineWidth = 0;

    if( line < 0 || line >= textArea.getLineCount() )
    {
      if( paintInvalid )
      {
        paintHighlight( gfx, line, y );
        styles[Token.INVALID].setGraphicsFlags( gfx, defaultFont );
        gfx.drawString( "~", 0, y + fm.getHeight() );
      }
    }
    else if( tokenMarker == null )
    {
      lineWidth = paintPlainLine( gfx, line, defaultFont, defaultColor, x, y );
    }
    else
    {
      lineWidth = paintSyntaxLine( gfx, tokenMarker, line, defaultFont, defaultColor, x, y );
    }

    if( lineWidth > areaWidth )
      areaWidth = lineWidth;
  }

  protected int paintPlainLine( Graphics gfx, int line, Font defaultFont, Color defaultColor, int x, int y )
  {
    paintHighlight( gfx, line, y );
    textArea.getLineText( line, currentLine );

    gfx.setFont( defaultFont );
    gfx.setColor( defaultColor );

    y += fm.getHeight();
    x = Utilities.drawTabbedText( currentLine, x, y, gfx, this, 0 );

    if( eolMarkers )
    {
      gfx.setColor( eolMarkerColor );
      gfx.drawString( ".", x, y );
    }

    return x;
  }

  protected int paintSyntaxLine( Graphics gfx, TokenMarker tokenMarker, int line, Font defaultFont,
      Color defaultColor, int x, int y )
  {
    textArea.getLineText( currentLineIndex, currentLine );
    currentLineTokens = tokenMarker.markTokens( currentLine, currentLineIndex );

    paintHighlight( gfx, line, y );

    gfx.setFont( defaultFont );
    gfx.setColor( defaultColor );
    y += fm.getHeight();
    x = SyntaxUtilities.paintSyntaxLine( currentLine, currentLineTokens, styles, this, gfx, x, y );

    if( eolMarkers )
    {
      gfx.setColor( eolMarkerColor );
      gfx.drawString( ".", x, y );
    }

    return x;
  }

  protected void paintHighlight( Graphics gfx, int line, int y )
  {
    if( line >= textArea.getSelectionStartLine() && line <= textArea.getSelectionEndLine() )
      paintLineHighlight( gfx, line, y );

    if( highlights != null )
      highlights.paintHighlight( gfx, line, y );

    if( bracketHighlight && line == textArea.getBracketLine() )
      paintBracketHighlight( gfx, line, y );

    if( line == textArea.getCaretLine() )
      paintCaret( gfx, line, y );
  }

  protected void paintLineHighlight( Graphics gfx, int line, int y )
  {
    int height = fm.getHeight();
    y += fm.getLeading() + fm.getMaxDescent();

    int selectionStart = textArea.getSelectionStart();
    int selectionEnd = textArea.getSelectionEnd();

    if( selectionStart == selectionEnd )
    {
      if( lineHighlight )
      {
        gfx.setColor( lineHighlightColor );
        gfx.fillRect( 0, y, getWidth(), height );
      }
    }
    else
    {
      gfx.setColor( selectionColor );

      int selectionStartLine = textArea.getSelectionStartLine();
      int selectionEndLine = textArea.getSelectionEndLine();
      int lineStart = textArea.getLineStartOffset( line );

      int x1, x2;
      if( textArea.isSelectionRectangular() )
      {
        int lineLen = textArea.getTabExpandedLineLength( line );
        x1 = textArea._offsetToX( line,
            Math.min( lineLen, selectionStart - textArea.getLineStartOffset( selectionStartLine ) ) );
        x2 = textArea._offsetToX( line,
            Math.min( lineLen, selectionEnd - textArea.getLineStartOffset( selectionEndLine ) ) );
        if( x1 == x2 )
          x2++ ;
      }
      else if( selectionStartLine == selectionEndLine )
      {
        x1 = textArea._offsetToX( line, selectionStart - lineStart );
        x2 = textArea._offsetToX( line, selectionEnd - lineStart );
      }
      else if( line == selectionStartLine )
      {
        x1 = textArea._offsetToX( line, selectionStart - lineStart );
        x2 = getWidth();
      }
      else if( line == selectionEndLine )
      {
        x1 = 0;
        x2 = textArea._offsetToX( line, selectionEnd - lineStart );
      }
      else
      {
        x1 = 0;
        x2 = getWidth();
      }

      // "inlined" min/max()
      gfx.fillRect( x1 > x2 ? x2 : x1, y, x1 > x2 ? ( x1 - x2 ) : ( x2 - x1 ), height );
    }

  }

  protected void paintBracketHighlight( Graphics gfx, int line, int y )
  {
    int position = textArea.getBracketPosition();
    if( position == -1 )
      return;
    y += fm.getLeading() + fm.getMaxDescent();
    int x = textArea._offsetToX( line, position );
    gfx.setColor( bracketHighlightColor );
    // Hack!!! Since there is no fast way to get the character
    // from the bracket matching routine, we use ( since all
    // brackets probably have the same width anyway
    gfx.drawRect( x, y, fm.charWidth( '(' ) - 1, fm.getHeight() - 1 );
  }

  protected void paintCaret( Graphics gfx, int line, int y )
  {
    if( textArea.isCaretVisible() )
    {
      int offset = textArea.getCaretPosition() - textArea.getLineStartOffset( line );
      int caretX = textArea._offsetToX( line, offset );
      int caretWidth = ( ( blockCaret || textArea.isOverwriteEnabled() ) ? fm.charWidth( 'w' ) : 1 );
      y += fm.getLeading() + fm.getMaxDescent();
      int height = fm.getHeight();

      gfx.setColor( caretColor );

      if( textArea.isOverwriteEnabled() )
      {
        gfx.fillRect( caretX, y + height - 1, caretWidth, 1 );
      }
      else
      {
        gfx.drawRect( caretX, y, caretWidth, height - 1 );
      }
    }
  }
}
TOP

Related Classes of org.syntax.jedit.TextAreaPainter$Highlight

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.