alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Groovy example source code file (ConsoleTextEditor.java)

This example Groovy source code file (ConsoleTextEditor.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Groovy tags/keywords

action, awt, bean, dimension, event, gui, jpanel, linenumberspanel, linenumberspanel, printaction, printaction, redoaction, redoaction, string, swing, text, texteditor, undoaction, undoaction, updatecaretlistener

The Groovy ConsoleTextEditor.java source code

/*
 * Copyright 2003-2010 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package groovy.ui;

import groovy.ui.text.GroovyFilter;
import groovy.ui.text.StructuredSyntaxResources;
import groovy.ui.text.TextEditor;
import groovy.ui.text.TextUndoManager;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.KeyStroke;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Document;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.print.PrinterJob;
import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.prefs.Preferences;

import org.codehaus.groovy.runtime.DefaultGroovyMethods;

/**
 * Component which provides a styled editor for the console.
 *
 * @author hippy
 * @author Danno Ferrin
 * @author Tim Yates
 * @author Guillaume Laforge
 */
public class ConsoleTextEditor extends JScrollPane {
    public String getDefaultFamily() {
        return defaultFamily;
    }

    public void setDefaultFamily(String defaultFamily) {
        this.defaultFamily = defaultFamily;
    }

    private class LineNumbersPanel extends JPanel {

        public LineNumbersPanel() {
            int initialSize = 3 * Preferences.userNodeForPackage(Console.class).getInt("fontSize", 12);
            setMinimumSize(new Dimension(initialSize, initialSize));
            setPreferredSize(new Dimension(initialSize, initialSize));
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            // starting position in document
            int start = textEditor.viewToModel(getViewport().getViewPosition());
            // end position in document
            int end = textEditor.viewToModel(new Point(10,
                    getViewport().getViewPosition().y +
                            (int) textEditor.getVisibleRect().getHeight())
            );

            // translate offsets to lines
            Document doc = textEditor.getDocument();
            int startline = doc.getDefaultRootElement().getElementIndex(start) + 1;
            int endline = doc.getDefaultRootElement().getElementIndex(end) + 1;
            Font f = textEditor.getFont();
            int fontHeight = g.getFontMetrics(f).getHeight();
            int fontDesc = g.getFontMetrics(f).getDescent();
            int startingY = -1;

            try {
                startingY = textEditor.modelToView(start).y + fontHeight - fontDesc;
            } catch (BadLocationException e1) {
                System.err.println(e1.getMessage());
            }
            g.setFont(f);
            for (int line = startline, y = startingY; line <= endline; y += fontHeight, line++) {
                String lineNumber = DefaultGroovyMethods.padLeft(Integer.toString(line), 4, " ");
                g.drawString(lineNumber, 0, y);
            }
        }
    }

    private String defaultFamily = "Monospaced";

    private static final PrinterJob PRINTER_JOB = PrinterJob.getPrinterJob();

    private LineNumbersPanel numbersPanel = new LineNumbersPanel();

    private boolean documentChangedSinceLastRepaint = false;

    private TextEditor textEditor = new TextEditor(true, true, true) {

        public void paintComponent(Graphics g) {
            super.paintComponent(g);

            // only repaint the line numbers in the gutter when the document has changed
            // in case lines (hence line numbers) have been added or removed from the document
            if (documentChangedSinceLastRepaint) {
                numbersPanel.repaint();
                documentChangedSinceLastRepaint = false;
            }
        }
    };

    private UndoAction undoAction = new UndoAction();
    private RedoAction redoAction = new RedoAction();
    private PrintAction printAction = new PrintAction();

    private boolean editable = true;

    private TextUndoManager undoManager;

    /**
     * Creates a new instance of ConsoleTextEditor
     */
    public ConsoleTextEditor() {
        textEditor.setFont(new Font(defaultFamily, Font.PLAIN, Preferences.userNodeForPackage(Console.class).getInt("fontSize", 12)));
        
        setViewportView(new JPanel(new BorderLayout()) {{
            add(numbersPanel, BorderLayout.WEST);
            add(textEditor, BorderLayout.CENTER);
        }});

        textEditor.setDragEnabled(editable);

        getVerticalScrollBar().setUnitIncrement(10);

        initActions();

        DefaultStyledDocument doc = new DefaultStyledDocument();
        doc.setDocumentFilter(new GroovyFilter(doc));
        textEditor.setDocument(doc);

        // add a document listener, to hint whether the line number gutter has to be repainted
        // when the number of lines changes
        doc.addDocumentListener(new DocumentListener() {
            public void insertUpdate(DocumentEvent documentEvent) {
                documentChangedSinceLastRepaint = true;
            }

            public void removeUpdate(DocumentEvent documentEvent) {
                documentChangedSinceLastRepaint = true;
            }

            public void changedUpdate(DocumentEvent documentEvent) {
                documentChangedSinceLastRepaint = true;
                int width = 3 * Preferences.userNodeForPackage(Console.class).getInt("fontSize", 12);
                numbersPanel.setPreferredSize(new Dimension(width, width));
            }
        });

        // create and add the undo/redo manager
        this.undoManager = new TextUndoManager();
        doc.addUndoableEditListener(undoManager);

        // add the undo actions
        undoManager.addPropertyChangeListener(undoAction);
        undoManager.addPropertyChangeListener(redoAction);

        doc.addDocumentListener(undoAction);
        doc.addDocumentListener(redoAction);

        InputMap im = textEditor.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
        KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_MASK, false);
        im.put(ks, StructuredSyntaxResources.UNDO);
        ActionMap am = textEditor.getActionMap();
        am.put(StructuredSyntaxResources.UNDO, undoAction);

        ks = KeyStroke.getKeyStroke(KeyEvent.VK_Y, InputEvent.CTRL_MASK, false);
        im.put(ks, StructuredSyntaxResources.REDO);
        am.put(StructuredSyntaxResources.REDO, redoAction);

        ks = KeyStroke.getKeyStroke(KeyEvent.VK_P, InputEvent.CTRL_MASK, false);
        im.put(ks, StructuredSyntaxResources.PRINT);
        am.put(StructuredSyntaxResources.PRINT, printAction);
    }

    public void setShowLineNumbers(boolean showLineNumbers) {
        if (showLineNumbers) {
            setViewportView(new JPanel(new BorderLayout()) {{
                add(numbersPanel, BorderLayout.WEST);
                add(textEditor, BorderLayout.CENTER);
            }});
        } else {
            setViewportView(textEditor);
        }
    }

    public void setEditable(boolean editable) {
        textEditor.setEditable(editable); 
    }

    public boolean clipBoardAvailable() {
        Transferable t = StructuredSyntaxResources.SYSTEM_CLIPBOARD.getContents(this);
        return t.isDataFlavorSupported(DataFlavor.stringFlavor);
    }

    public TextEditor getTextEditor() {
        return textEditor;
    }

    protected void initActions() {
        ActionMap map = getActionMap();

        PrintAction printAction = new PrintAction();
        map.put(StructuredSyntaxResources.PRINT, printAction);
    }

    private class PrintAction extends AbstractAction {

        public PrintAction() {
            setEnabled(true);
        }

        public void actionPerformed(ActionEvent ae) {
            PRINTER_JOB.setPageable(textEditor);

            try {
                if (PRINTER_JOB.printDialog()) {
                    PRINTER_JOB.print();
                }
            }
            catch (Exception e) {
                e.printStackTrace();
            }
        }
    } // end ConsoleTextEditor.PrintAction

    private class RedoAction extends UpdateCaretListener implements PropertyChangeListener {

        public RedoAction() {
            setEnabled(false);
        }

        public void actionPerformed(ActionEvent ae) {
            undoManager.redo();
            setEnabled(undoManager.canRedo());
            undoAction.setEnabled(undoManager.canUndo());
            super.actionPerformed(ae);
        }

        public void propertyChange(PropertyChangeEvent pce) {
            setEnabled(undoManager.canRedo());
        }
    } // end ConsoleTextEditor.RedoAction

    private abstract class UpdateCaretListener extends AbstractAction implements DocumentListener {

        protected int lastUpdate;

        public void changedUpdate(DocumentEvent de) {
        }

        public void insertUpdate(DocumentEvent de) {
            lastUpdate = de.getOffset() + de.getLength();
        }

        public void removeUpdate(DocumentEvent de) {
            lastUpdate = de.getOffset();
        }

        public void actionPerformed(ActionEvent ae) {
            textEditor.setCaretPosition(lastUpdate);
        }
    }

    private class UndoAction extends UpdateCaretListener implements PropertyChangeListener {

        public UndoAction() {
            setEnabled(false);
        }

        public void actionPerformed(ActionEvent ae) {
            undoManager.undo();
            setEnabled(undoManager.canUndo());
            redoAction.setEnabled(undoManager.canRedo());
            super.actionPerformed(ae);
        }

        public void propertyChange(PropertyChangeEvent pce) {
            setEnabled(undoManager.canUndo());
        }
    }

    public Action getUndoAction() {
        return undoAction;
    }

    public Action getRedoAction() {
        return redoAction;
    }

    public Action getPrintAction() {
        return printAction;
    }

}

Other Groovy examples (source code examples)

Here is a short list of links related to this Groovy ConsoleTextEditor.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.