All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.cayenne.swing.components.textpane.JCayenneTextPane Maven / Gradle / Ivy

There is a newer version: 5.0-M1
Show newest version
/*****************************************************************
 *   Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you 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
 *
 *    https://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 org.apache.cayenne.swing.components.textpane;

import org.apache.cayenne.modeler.Main;
import org.apache.cayenne.modeler.util.ModelerUtil;
import org.apache.cayenne.swing.components.textpane.syntax.SQLSyntaxConstants;
import org.apache.cayenne.swing.components.textpane.syntax.SyntaxConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.JViewport;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Highlighter;
import javax.swing.text.JTextComponent;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;

public class JCayenneTextPane extends JPanel {

    protected Highlighter.HighlightPainter painter;
    private JTextPaneScrollable pane;
    private JScrollPane scrollPane;

    private boolean imageError;
    private String tooltipTextError;
    private int startYPositionToolTip;
    private int endYPositionToolTip;

    public JScrollPane getScrollPane() {
        return scrollPane;
    }

    public String getTooltipTextError() {
        return tooltipTextError;
    }

    public void setTooltipTextError(String tooltipTextError) {
        this.tooltipTextError = tooltipTextError;
    }

    private static Logger logObj = LoggerFactory.getLogger(Main.class);

    public void setText(String text) {
        pane.setText(text);
    }

    public String getText() {
        return pane.getText();
    }

    public JTextComponent getPane() {
        return pane;
    }

    public int getStartPositionInDocument() {
        return pane.viewToModel(scrollPane.getViewport().getViewPosition());
    }

    public int getEndPositionInDocument() {
        return pane.viewToModel(new Point(scrollPane.getViewport().getViewPosition().x + pane.getWidth(),
                scrollPane.getViewport().getViewPosition().y + pane.getHeight()));
    }

    public void repaintPane() {
        pane.repaint();
    }

    /**
     * Return an int containing the wrapped line index at the given position
     * 
     * @param pos int
     * @return int
     */
    public int getLineNumber(int pos) {
        int posLine;
        int y = 0;

        try {
            Rectangle caretCoords = pane.modelToView(pos);
            y = (int) caretCoords.getY();
        } catch (BadLocationException ex) {
            logObj.warn("Error: ", ex);
        }

        int lineHeight = pane.getFontMetrics(pane.getFont()).getHeight();
        posLine = (y / lineHeight) + 1;
        return posLine;
    }

    /**
     * Return an int position at the given line number and symbol position in this line
     * 
     * @param posInLine int
     * @param line int
     * @return int
     * @throws BadLocationException
     */
    public int getPosition(int line, int posInLine) throws BadLocationException {
        // translate lines to offsets
        int position = -1;
        int numrows = 1;
        char[] chararr = pane.getText().toCharArray();
        for (int i = 0; i < chararr.length; i++) {
            if (chararr[i] == '\n') {
                numrows++;
                if (numrows == line) {
                    position = i;
                    break;
                }
            }
        }
        return position + posInLine;
    }

    public JCayenneTextPane(SyntaxConstant syntaxConstant) {
        super();

        Dimension dimension = new Dimension(15, 15);
        setMinimumSize(dimension);
        setPreferredSize(dimension);
        setMinimumSize(dimension);
        setBorder(null);

        pane = new JTextPaneScrollable(new EditorKit(syntaxConstant)) {
            public void paint(Graphics g) {
                super.paint(g);
                JCayenneTextPane.this.repaint();
            }
        };

        pane.setFont(SQLSyntaxConstants.DEFAULT_FONT);
        pane.setBorder(new LineNumberedBorder(this));

        scrollPane = new JScrollPane(pane);
        scrollPane.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
        painter = new UnderlineHighlighterForText.UnderlineHighlightPainter(Color.red);

        pane.getDocument().addDocumentListener(new DocumentListener() {
            public void insertUpdate(DocumentEvent evt) {
                try {
                    String text = pane.getText(evt.getOffset(), 1);
                    if (text.equals("/") || text.equals("*")) {
                        removeHighlightText();
                        pane.repaint();
                    } else if (text.equals(" ") || text.equals("\t") || text.equals("\n")) {
                        pane.repaint();
                    }
                } catch (Exception e) {
                    logObj.warn("Error: ", e);
                }
            }

            public void removeUpdate(DocumentEvent evt) {
            }

            public void changedUpdate(DocumentEvent evt) {
            }
        });

    }

    public void setHighlightText(int lastIndex, int endIndex) throws BadLocationException {
        Highlighter highlighter = pane.getHighlighter();
        removeHighlightText(highlighter);
        highlighter.addHighlight(lastIndex, endIndex, painter);
    }

    /**
     * set underlines text in JCayenneTextPane
     * 
     * @param line int - starting line for underlined text
     * @param lastIndex int - starting position in line for underlined text
     * @param size int
     * @param message String - text for toolTip, contains the text of the error
     */

    public void setHighlightText(int line, int lastIndex, int size, String message) {
        Highlighter highlighter = pane.getHighlighter();
        removeHighlightText(highlighter);
        if (getText().length() > 0) {
            try {
                int position = getPosition(line, lastIndex);
                int positionEnd = position + size;
                highlighter.addHighlight(position, positionEnd, painter);
                setToolTipPosition(line, message);
                repaintPane();
            } catch (BadLocationException e) {
                logObj.warn("Error: ", e);
            }
        } else {
            setToolTipPosition(0, "");
        }
    }

    public void removeHighlightText(Highlighter highlighter) {
        Highlighter.Highlight[] highlights = highlighter.getHighlights();
        for (Highlighter.Highlight h : highlights) {
            if (h.getPainter() instanceof UnderlineHighlighterForText.UnderlineHighlightPainter) {
                highlighter.removeHighlight(h);
            }
        }
    }

    public void setToolTipPosition(int line, String string) {
        if (line != 0) {
            int height = pane.getFontMetrics(pane.getFont()).getHeight();
            int start = (line - 1) * height;
            this.endYPositionToolTip = start;
            this.startYPositionToolTip = start + height;
            setTooltipTextError(string);
            imageError = !"".equals(string);
            setToolTipText("");
        } else {
            this.endYPositionToolTip = -1;
            this.startYPositionToolTip = -1;
            setTooltipTextError("");
            setToolTipText("");
            imageError = false;
        }
    }

    public String getToolTipText(MouseEvent e) {

        if (e.getPoint().y > endYPositionToolTip
                && e.getPoint().y < startYPositionToolTip
                && imageError) {
            setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
            String htmlText = getTooltipTextError()
                    .replaceAll("\n", "
 ") .replaceAll("\t", " ") .replaceAll("\r", "
 "); return "" + "" + htmlText + ""; } else { setCursor(Cursor.getDefaultCursor()); return null; } } public void removeHighlightText() { imageError = false; Highlighter highlighter = pane.getHighlighter(); removeHighlightText(highlighter); } public int getCaretPosition() { return pane.getCaretPosition(); } public void paint(Graphics g) { super.paint(g); int start = getStartPositionInDocument(); int end = getEndPositionInDocument(); // end pos in doc // translate offsets to lines Document doc = pane.getDocument(); int startline = doc.getDefaultRootElement().getElementIndex(start) + 1; int endline = doc.getDefaultRootElement().getElementIndex(end) + 1; int fontHeight = g.getFontMetrics(pane.getFont()).getHeight(); int fontDesc = g.getFontMetrics(pane.getFont()).getDescent(); int starting_y = -1; try { if (pane.modelToView(start) == null) { starting_y = -1; } else { starting_y = pane.modelToView(start).y - scrollPane.getViewport().getViewPosition().y + fontHeight - fontDesc; } } catch (Exception e1) { logObj.warn("Error: ", e1); } for (int line = startline, y = starting_y; line <= endline; y += fontHeight, line++) { Color color = g.getColor(); if (line - 1 == doc.getDefaultRootElement().getElementIndex(pane.getCaretPosition())) { g.setColor(new Color(224, 224, 255)); g.fillRect(0, y - fontHeight + 3, 30, fontHeight + 1); } if (imageError) { Image img = ModelerUtil.buildIcon("icon-error.png").getImage(); g.drawImage(img, 0, endYPositionToolTip, this); } g.setColor(color); } } public Document getDocument() { return pane.getDocument(); } public void setDocumentTextDirect(String text) { Document document = getDocument(); try { if(!document.getText(0, document.getLength()).equals(text)) { document.remove(0, document.getLength()); document.insertString(0, text, null); } } catch (BadLocationException ex) { logObj.warn("Error reading document", ex); } } public String getDocumentTextDirect() { Document document = getDocument(); try { return document.getText(0, document.getLength()); } catch (BadLocationException ex) { logObj.warn("Error reading document", ex); return null; } } class JTextPaneScrollable extends JTextPane { JTextPaneScrollable(EditorKit editorKit) { // Set editor kit this.setEditorKitForContentType(editorKit.getContentType(), editorKit); this.setContentType(editorKit.getContentType()); } @Override public boolean getScrollableTracksViewportWidth() { if (getParent() instanceof JViewport) { JViewport port = (JViewport) getParent(); if (port.getWidth() > getUI().getPreferredSize(this).width) { return true; } } return false; } @Override public void paintComponent(Graphics g) { super.paintComponent(g); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy