package main; import javax.swing.*; import javax.swing.text.*; import java.awt.Point; import java.awt.event.*; import java.awt.AWTEventMulticaster; import java.io.*; import java.lang.*; public class NetworkFile extends DefaultStyledDocument { StyleContext styles = new StyleContext(); AttributeSet attributes = styles.getEmptySet(); private ActionListener actionListener = null; public NetworkFile() { TabStop [] stops = new TabStop[20]; for(int i = 0; i < 20; i++) { stops[i] = new TabStop(i * 20); } TabSet tabset = new TabSet(stops); attributes = styles.addAttribute(attributes, StyleConstants.TabSet, tabset); } /** Reads in a model file from a stream, which will usually be a file stream. Currently this is a very simple function that just puts the text into the document exactly as it comes in on the stream. In the future, this function might want to parse the text and set different styles for different tokens in the file. Or perhaps there should be a separate parsing function that gets called afterwards. */ public void readText(InputStream stream) throws Exception { byte [] text = new byte[1024]; // First get rid of the old text in the document remove(0, getLength()); // Then read in new text in chunks int len = stream.read(text); while(len > 0) { insertString(getLength(), new String(text, 0, len), attributes); len = stream.read(text); } setParagraphAttributes(0, getLength(), attributes, true); } /** Make a new Model from the currently stored text. If the model is successfully created, returns the Model. Otherwise, returns null. TO DO: when there is an error, position cursor at the error and put up the error message. */ public Model createModel() { try { String model_text = getText(0, getLength()); StringReader stream = new StringReader(model_text); BetterTokenizer tokenizer = new BetterTokenizer(stream); GeneralInput.setupTokenizer(tokenizer); Model model = new Model(); model.load(tokenizer); return model; } catch(ModelLoadingException e) { System.out.println(e.toString()); hiliteLine(e.getLineNo()); return null; } catch(BadLocationException e) { // Shouldn't ever happen return null; } catch(Exception e) { // In here, put cursor at error line and print error string somewhere System.out.println(e.toString()); hiliteLine(-1); return null; } } public void hiliteLine(int line) { int l = 0, c = 0, c1 = 0, c2 = 0; if(actionListener != null) { // Figure out where the start and end of this line is if(line < 0) { actionListener.actionPerformed(new ActionEvent(new Point(0, 0), ActionEvent.ACTION_PERFORMED, "HiliteNetworkFileLine")); return; } // First get the text int length = getLength(); Segment text = new Segment(); try { getText(0, length, text); } catch(BadLocationException e) { // just punt return; } // Search through for line endings since no convenient java functions to do this while(l < line && c < length) { if(text.array[c] == '\r') { l++; if(c + 1 < length && text.array[c+1] == '\n') c++; // For windows strings } else if(text.array[c] == '\n') { l++; } c++; } if(l < line) c1 = c2 = 0; else { c1 = c; // Find the end of the line while(c < length && text.array[c] != '\n' && text.array[c] != '\r') c++; c2 = c; } actionListener.actionPerformed(new ActionEvent(new Point(c1, c2), ActionEvent.ACTION_PERFORMED, "HiliteNetworkFileLine")); } // if(actionListener != null) } // Stock code for sending out action events public void addActionListener(ActionListener l) { actionListener = AWTEventMulticaster.add(actionListener, l); } public void removeActionListener(ActionListener l) { actionListener = AWTEventMulticaster.remove(actionListener, l); } }