//
// CodeEditor.java
//

/*
VisAD system for interactive analysis and visualization of numerical
data.  Copyright (C) 1996 - 2017 Bill Hibbard, Curtis Rueden, Tom
Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and
Tommy Jasmin.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.

This library 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
Library General Public License for more details.

You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA
*/

package visad.util;

import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.undo.*;
import visad.VisADException;

/** An editor for writing and executing source code in Java runtime. */
public abstract class CodeEditor extends TextEditor {

  /** text pane containing line numbers */
  protected JTextArea lineNumbers;

  /** number of lines of code in the document */
  protected int numLines;

  /** number of digits in lines of code in the document */
  protected int numDigits;

  /** constructs a CodeEditor */
  public CodeEditor() {
    this(null);
  }

  /** constructs a CodeEditor containing text from the given filename */
  public CodeEditor(String filename) {
    super(filename);

    // set up line numbers
    final int fontWidth = getFontMetrics(MONO).stringWidth(" ");
    lineNumbers = new JTextArea("1") {
      public Dimension getPreferredSize() {
        Dimension d = super.getPreferredSize();
        d.width = numDigits * fontWidth;
        return d;
      }
    };
    lineNumbers.setEditable(false);
    lineNumbers.setFont(MONO);
    numLines = 1;
    numDigits = 1;
    JPanel p = new JPanel() {
      public void paint(Graphics g) {
        // paint a thin gray line down right-hand side of line numbering
        super.paint(g);
        Dimension d = getSize();
        int w = d.width - 5;
        int h = d.height - 1;
        g.setColor(Color.gray);
        g.drawLine(w, 0, w, h);
      }

      public Dimension getPreferredSize() {
        Dimension d = lineNumbers.getPreferredSize();
        d.width += 10;
        return d;
      }
    };
    p.setBackground(Color.white);
    p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
    p.add(lineNumbers);
    setRowHeaderView(p);
  }

  /** highlights the given line of code in the document */
  public void highlightLine(int line) {
    int start = 0;
    String s = text.getText() + "\n";
    for (int i=0; i= 0) {
      count++;
      index = s.indexOf("\n", index + 1);
    }
    if (count == numLines) return;

    // compute index into line numbers text string
    String l = lineNumbers.getText() + "\n";
    int digits = ("" + count).length();
    int spot = 0;
    int nine = 9;
    for (int i=2; i<=digits; i++) {
      spot += i * nine;
      nine *= 10;
    }
    int ten = nine / 9;
    spot += (digits + 1) * (count - ten + 1);

    // update line numbers text string
    int maxSpot = l.length();
    String newL;
    if (spot < maxSpot) {
      // eliminate extra line numbers
      newL = l.substring(0, spot - 1);
    }
    else {
      // append additional line numbers
      StringBuffer sb = new StringBuffer(spot);
      sb.append(l);
      for (int i=numLines+1; i 

Ads help maintain this website.