📄 codepanel.java
字号:
package ai.common;
import java.net.*;
import java.io.*;
import java.util.*;
import java.awt.*;
import javax.swing.*;
/**
* A CodePanel displays pseudo-code in a scrollable, highlightable window.
*
* <p>
* CodePanel expects pseudo-code files to conform to a specific
* syntax. Functions are identified by the <code><function>
* </code> HTML-like pseudo-tag (with a <code></function>
* </code> closing tag). A line break in the pseudo-code is marked
* by a period, which should be the last non-whitespace
* character on a line. The periods are automatically stripped before the
* text is stored.
*
* <p>
* <b>Change History:</b>
*
* <p><pre>
* Name: Date: Change:
* =============================================================
* J. Kelly May-31-2000 Created. Based on original
* work by S. Nychka.
* J. Kelly Jun-04-2000 Added Highlighter interface.
* J. Kelly Jul-10-2000 Added dynamic text display
* capability.
* J. Kelly Oct-01-2000 Revised with
* HighlightListener interface.
* </pre>
*
* Copyright 2000 University of Alberta.
*
* <!--
* This file is part of the Decision Tree Applet.
*
* The Decision Tree Applet is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* Foobar 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the Decision Tree Applet; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* -->
*/
public class CodePanel
extends JPanel
implements HighlightListener
{
// Class data members
// Marks the beginning of a function tag.
private static final String FUNCTION_START = "<function";
// Marks the start of the name of a function (inside
// the 'function' tag).
private static final String NAME_START = "name=\"";
// Marks the end of the name of a function (inside
// the 'function' tag).
private static final String NAME_END = "\">";
// Marks the end of a function.
private static final String FUNCTION_END = "</function>";
// Marks a tab insertion point.
private static final String TAB_MARKER = "<tab>";
// HTML character string that replaces a tab marker.
private static final String TAB = " ";
// Marks the start of a dynamic portion of algorithm
// text. A custom text string can be inserted between
// a pair of 'dynamic' tags.
private static final String DYNAMIC_START = "<meta";
// Marks the end of a dynamic portion of algorithm text.
private static final String DYNAMIC_END = "</meta>";
// This string must preceed every line - it
// informs JLabel that the text should be rendered
// as HTML, and sets the #&&@! font size
private static final String HTML_LINE_HEADER = "<html><font size=-2>";
// This string terminates every line.
private static final String HTML_LINE_TERMINATOR = "</font>";
// The height of each cell in the list. This can
// be adjusted, depending on the size of the text, to
// keep the rows as closely spaced as possible.
// Otherwise, the default JLabel renderer tends to
// add too much excess space above and below each line
// of text.
private static final int ROW_HEIGHT = 16;
// Instance data members
// A Vector of functions, where each function is a Vector of
// Strings, and each String is one line of code.
private Vector m_functions;
// Vector in parallel to 'functions', which contains the names
// of each function.
private Vector m_functionNames;
// Name of the function currently being displayed.
String m_functionName;
// The list that displays the code.
JList m_list;
// Constructors
/**
* Builds a new CodePanel. The panel initially
* displays the first function parsed from the
* pseudo-code file.
*
* @param repository The URL where available code text
* is located.
*
* @param codeFile The file to read code text from. The
* method attempts to open the effective URL:
* repository + codeFile for reading.
*
* @throws NullPointerException If the supplied URL
* is null.
*
* @throws MalformedURLException If the URL protocol is
* unrecognized.
*
* @throws IOException If a problem occurs while
* reading data from the specified URL.
*
* @throws InvalidCodeFileException If the code file
* contains syntax errors.
*/
public CodePanel( URL repository, String codeFile )
throws MalformedURLException,
IOException,
InvalidCodeFileException
{
super();
if( repository == null )
throw new NullPointerException( "Repository URL is null." );
// Build the panel structure.
buildPanel();
// Load and parse the code file.
CodeReader codeSrc = new CodeReader( repository );
Vector lines = codeSrc.read( codeFile, false );
parseLines( lines );
}
// Public methods
/**
* Returns a Vector which contains the names of all functions that
* are available for display.
*
* @return A Vector of Strings, where each String is the name of a
* function that can be displayed.
*/
public Vector getFunctionNames()
{
return (Vector)m_functionNames.clone();
}
/**
* Returns the number of functions that are available for display.
*
* @return The total number of functions stored and available for display.
*/
public int getNumFunctions()
{
return m_functions.size();
}
/**
* Searches for the function with the given function
* name, and locates the line containing a dynamic text
* tag with the supplied 'dynamic' ID. Replaces any
* text between the dynamic tags with <code>text</code>
*
* <p>
* If no function with the supplied name exists, or the
* function doesn't contain the dynamic name tag, no
* changes are made.
*
* @param functionName The name of the function in which
* text should be modified.
*
* @param dynamicName The name of the 'dynamic' pseudo-tag
* (embedded in the tag itself) to locate. Any
* text between the opening and closing dynamic
* tags will be replaced.
*
* @param text The replacement text string.
*/
public void setDynamicText( final String functionName,
final String dynamicName,
final String text )
{
Runnable setDynamicText =
new Runnable() {
public void run() {
// Find the function with the supplied name.
int functionNum = -1;
for( int i = 0; i < m_functionNames.size(); i++ )
if( ((String) m_functionNames.elementAt( i ))
.equals( functionName ) )
functionNum = i;
if( functionNum == -1 ) return; // Didn't find it.
Vector functionVec = (Vector)m_functions.elementAt( functionNum );
// Locate a line that contains the dynamic tag with
// the supplied name.
for( int j = 0; j < functionVec.size(); j++ ) {
int pos = 0;
String line = (String)functionVec.elementAt( j );
while( (pos = line.indexOf( DYNAMIC_START, pos )) != -1 ) {
// Check to see if the name is correct.
// We don't do any rigorous syntax checking here.
pos = line.indexOf( NAME_START, pos + DYNAMIC_START.length() );
if( pos == -1 ) break;
int nameStart = pos + NAME_START.length();
int nameEnd = line.indexOf( NAME_END,
pos + NAME_START.length() );
String name = line.substring( nameStart, nameEnd );
if( !name.equals( dynamicName ) ) break;
// We've got a match - figure out where the closing dynamic
// tag is, and replace all the text in between.
int dynamicEnd =
line.indexOf( DYNAMIC_END, nameEnd + NAME_END.length() );
if( dynamicEnd == -1 ) break;
functionVec.set( j, new String(
line.substring( 0, nameEnd + NAME_END.length() ) +
text + line.substring( dynamicEnd ) ) );
}
}
if( m_functionName != null && m_functionName.equals( functionName ) )
// We need to refresh the display.
displayFunction( m_functionName );
}
};
try {
if( SwingUtilities.isEventDispatchThread() )
setDynamicText.run();
else
SwingUtilities.invokeLater( setDynamicText );
}
catch( Exception e ) {
e.printStackTrace();
}
}
/**
* Displays the function with the supplied name
* in the code window. This method is thread-safe.
*
* @param name The name of the function to display.
* If no function with the supplied name
* exists, the display remains unchanged.
*/
public void displayFunction( final String name )
{
Runnable displayFunction =
new Runnable() {
public void run() {
// Locate the position of the function
// in the internal storage vector.
for( int i = 0; i < m_functionNames.size(); i++ )
if( ((String)m_functionNames.elementAt( i )).equals( name ) ) {
m_list.setListData( (Vector)m_functions.elementAt( i ) );
m_functionName = new String( name );
return;
}
}
};
try {
if( SwingUtilities.isEventDispatchThread() )
displayFunction.run();
else
SwingUtilities.invokeLater( displayFunction );
}
catch( Exception e ) {
e.printStackTrace();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -