| TextWindow |

    package ij.text;

    import java.awt.*;
    import java.io.*;
    import java.awt.event.*;
    import ij.*;
    import ij.io.*;
    import ij.gui.*;
    import ij.plugin.filter.Analyzer;
    import ij.measure.ResultsTable;
    import ij.macro.Interpreter;

    /** Uses a TextPanel to displays text in a window.
        @see TextPanel
    */
    public class TextWindow extends Frame implements ActionListener, FocusListener, ItemListener {

        public static final String LOC_KEY = "results.loc";
        public static final String WIDTH_KEY = "results.width";
        public static final String HEIGHT_KEY = "results.height";
        static final String FONT_SIZE = "tw.font.size";
        static final String FONT_ANTI= "tw.font.anti";
        TextPanel textPanel;
        CheckboxMenuItem antialiased;
        int[] sizes = {9, 10, 11, 12, 13, 14, 16, 18, 20, 24, 36, 48, 60, 72};
        int fontSize = (int)Prefs.get(FONT_SIZE, 5);

        /**
        Opens a new single-column text window.
        @param title    the title of the window
        @param str      the text initially displayed in the window
        @param width    the width of the window in pixels
        @param height   the height of the window in pixels
        */
        public TextWindow(String title, String data, int width, int height) {
            this(title, "", data, width, height);
        }

        /**
        Opens a new multi-column text window.
        @param title    the title of the window
        @param headings the tab-delimited column headings
        @param data     the text initially displayed in the window
        @param width    the width of the window in pixels
        @param height   the height of the window in pixels
        */
        public TextWindow(String title, String headings, String data, int width, int height) {
            super(title);
            enableEvents(AWTEvent.WINDOW_EVENT_MASK);
            if (IJ.isLinux()) setBackground(ImageJ.backgroundColor);
            textPanel = new TextPanel(title);
            textPanel.setTitle(title);
            add("Center", textPanel);
            textPanel.setColumnHeadings(headings);
            if (data!=null && !data.equals(""))
                textPanel.append(data);
            addKeyListener(textPanel);
            ImageJ ij = IJ.getInstance();
            if (ij!=null) {
                Image img = ij.getIconImage();
                if (img!=null)
                    try {setIconImage(img);} catch (Exception e) {}
            }
            addFocusListener(this);
            addMenuBar();
            setFont();
            WindowManager.addWindow(this);

            Point loc=null;
            int w=0, h=0;
            if (title.equals("Results")) {
                loc = Prefs.getLocation(LOC_KEY);
                w = (int)Prefs.get(WIDTH_KEY, 0.0);
                h = (int)Prefs.get(HEIGHT_KEY, 0.0);
            }
            if (loc!=null && w>0 && h>0) {
                setSize(w, h);
                setLocation(loc);
            } else {
                setSize(width, height);
                GUI.center(this);
            }
            show();
        }

        /**
        Opens a new text window containing the contents
        of a text file.
        @param path     the path to the text file
        @param width    the width of the window in pixels
        @param height   the height of the window in pixels
        */
        public TextWindow(String path, int width, int height) {
            super("");
            enableEvents(AWTEvent.WINDOW_EVENT_MASK);
            textPanel = new TextPanel();
            add("Center", textPanel);
            if (openFile(path)) {
                WindowManager.addWindow(this);
                setSize(width, height);
                show();
            } else
                dispose();
        }

        void addMenuBar() {
            MenuBar mb = new MenuBar();
            if (Menus.getFontSize()!=0)
                mb.setFont(Menus.getFont());
            Menu m = new Menu("File");
            m.add(new MenuItem("Save As...", new MenuShortcut(KeyEvent.VK_S)));
            if (getTitle().equals("Results")) {
                m.addSeparator();
                m.add(new MenuItem("Set File Extension..."));
            }
            m.addActionListener(this);
            mb.add(m);
            m = new Menu("Edit");
            m.add(new MenuItem("Cut", new MenuShortcut(KeyEvent.VK_X)));
            m.add(new MenuItem("Copy", new MenuShortcut(KeyEvent.VK_C)));
            m.add(new MenuItem("Clear"));
            m.add(new MenuItem("Select All", new MenuShortcut(KeyEvent.VK_A)));
            if (getTitle().equals("Results")) {
                m.addSeparator();
                m.add(new MenuItem("Clear Results"));
                m.add(new MenuItem("Summarize"));
                m.add(new MenuItem("Distribution..."));
                m.add(new MenuItem("Set Measurements..."));
                m.add(new MenuItem("Duplicate..."));
            }
            m.addActionListener(this);
            mb.add(m);
            m = new Menu("Font");
            m.add(new MenuItem("Make Text Smaller"));
            m.add(new MenuItem("Make Text Larger"));
            m.addSeparator();
            antialiased = new CheckboxMenuItem("Antialiased", Prefs.get(FONT_ANTI, IJ.isMacOSX()?true:false));
            antialiased.addItemListener(this);
            m.add(antialiased);
            m.add(new MenuItem("Save Settings"));
            m.addActionListener(this);
            mb.add(m);
            setMenuBar(mb);
        }

        /**
        Adds one or lines of text to the window.
        @param text     The text to be appended. Multiple
                        lines should be separated by \n.
        */
        public void append(String text) {
            textPanel.append(text);
        }

        void setFont() {
            textPanel.setFont(new Font("SanSerif", Font.PLAIN, sizes[fontSize]), antialiased.getState());
        }

        boolean openFile(String path) {
            OpenDialog od = new OpenDialog("Open Text File...", path);
            String directory = od.getDirectory();
            String name = od.getFileName();
            if (name==null)
                return false;
            path = directory + name;

            IJ.showStatus("Opening: " + path);
            try {
                BufferedReader r = new BufferedReader(new FileReader(directory + name));
                load(r);
                r.close();
            }
            catch (Exception e) {
                IJ.error(e.getMessage());
                return true;
            }
            textPanel.setTitle(name);
            setTitle(name);
            IJ.showStatus("");
            return true;
        }

        /** Returns a reference to this TextWindow's TextPanel. */
        public TextPanel getTextPanel() {
            return textPanel;
        }

        /** Appends the text in the specified file to the end of this TextWindow. */
        public void load(BufferedReader in) throws IOException {
            int count=0;
            while (true) {
                String s=in.readLine();
                if (s==null) break;
                textPanel.appendLine(s);
            }
        }

        public void actionPerformed(ActionEvent evt) {
            String cmd = evt.getActionCommand();
            if (cmd.equals("Make Text Larger"))
                changeFontSize(true);
            else if (cmd.equals("Make Text Smaller"))
                changeFontSize(false);
            else if (cmd.equals("Save Settings"))
                saveSettings();
            else
                textPanel.doCommand(cmd);
        }

        public void processWindowEvent(WindowEvent e) {
            super.processWindowEvent(e);
            int id = e.getID();
            if (id==WindowEvent.WINDOW_CLOSING)
                close();
            else if (id==WindowEvent.WINDOW_ACTIVATED)
                WindowManager.setWindow(this);
        }

        public void itemStateChanged(ItemEvent e) {
            setFont();
        }

        public void close() {
            if (getTitle().equals("Results")) {
                if (!Analyzer.resetCounter())
                    return;
                IJ.setTextPanel(null);
                Prefs.saveLocation(LOC_KEY, getLocation());
                Dimension d = getSize();
                Prefs.set(WIDTH_KEY, d.width);
                Prefs.set(HEIGHT_KEY, d.height);
            } else if (getTitle().equals("Log")) {
                IJ.debugMode = false;
                IJ.log("\\Closed");
            } else if (textPanel!=null && textPanel.rt!=null) {
                if (!saveContents()) return;
            }
            setVisible(false);
            dispose();
            WindowManager.removeWindow(this);
            textPanel.flush();
        }

        boolean saveContents() {
            int lineCount = textPanel.getLineCount();
            if (!textPanel.unsavedLines) lineCount = 0;
            ImageJ ij = IJ.getInstance();
            boolean macro = IJ.macroRunning() || Interpreter.isBatchMode();
            if (lineCount>0 && !macro && ij!=null && !ij.quitting()) {
                YesNoCancelDialog d = new YesNoCancelDialog(this, getTitle(), "Save "+lineCount+" measurements?");
                if (d.cancelPressed())
                    return false;
                else if (d.yesPressed()) {
                    if (!textPanel.saveAs(""))
                        return false;
                }
            }
            textPanel.rt.reset();
            return true;
        }

        void changeFontSize(boolean larger) {
            int in = fontSize;
            if (larger) {
                fontSize++;
                if (fontSize==sizes.length)
                    fontSize = sizes.length-1;
            } else {
                fontSize--;
                if (fontSize<0)
                    fontSize = 0;
            }
            IJ.showStatus(sizes[fontSize]+" point");
            setFont();
        }

        void saveSettings() {
            Prefs.set(FONT_SIZE, fontSize);
            Prefs.set(FONT_ANTI, antialiased.getState());
            IJ.showStatus("Font settings saved (size="+sizes[fontSize]+", antialiased="+antialiased.getState()+")");
        }

        public void focusGained(FocusEvent e) {
            WindowManager.setWindow(this);
        }

        public void focusLost(FocusEvent e) {}

    }

| TextWindow |