package de.duehl.swing.ui.highlightingeditor.textcomponent;

/*
 * Copyright 2017 Christian Dühl. All rights reserved.
 *
 * This program is free software. You can redistribute it and/or
 * modify it under the same terms as perl:
 *
 * general:  http://dev.perl.org/licenses/
 * GPL:      http://dev.perl.org/licenses/gpl1.html
 * artistic: http://dev.perl.org/licenses/artistic.html
 */

import java.awt.Rectangle;

import javax.swing.JTextPane;
import javax.swing.JViewport;

import de.duehl.swing.ui.highlightingeditor.multiplereactor.ChangeReactor;

/**
 * Sacht erweiterte JTextPane.
 *
 * Eigentlich lässt sich das mit
 *     new JTextPane();
 * erledigen, doch es gab das Problem, dass nach dem Syntax Highlighting die aktuell
 * bearbeitete Zeile immer an Zeile 1 bewegt wurde.
 *
 * Mögliche Lösungsansätze waren:
 *
 * 1) https://stackoverflow.com/questions/31372997/jscrollpane-scroll-position-after-revalidate
 *
 * und das dort verlinkte
 *
 * 2) https://stackoverflow.com/questions/3972337/
 *                   java-swing-jtextarea-in-a-jscrollpane-how-to-prevent-auto-scroll#3973103
 *
 * Die mögliche Lösung aus dem zweiten Link, nämlich
 *
 *     DefaultCaret caret = (DefaultCaret)editor.getCaret();
 *     caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
 *
 * funktioniert in dem Sinne, dass die bearbeitete Zeile da bleibt, wo sie ist, aber der Cursor
 * des Editors bewegt sich dann bei Eingaben nicht mehr mit.
 *
 * So hat die erste Lösung den gewünschten Effekt gebracht, nämlich die Methode
 * scrollRectToVisible() zu überschrieben und darin nichts zu tun.
 *
 * @version 1.01     2017-11-21
 * @author Christian Dühl
 */

public class ScrollingSuppressingTextPane extends JTextPane implements ChangeReactor {

    private static final long serialVersionUID = 1L;

    /**
     * Gibt an, ob bei Veränderungen der Caretposition der sichtbare Bereich angepasst werden soll.
     */
    private boolean reactOnChanges;

    /** Konstruktor. */
    public ScrollingSuppressingTextPane() {
        doNotReactOnChanges();
    }

    /**
     * Gibt an, dass bei Veränderungen der Caretposition der sichtbare Bereich angepasst werden
     * soll.
     */
    @Override
    public void reactOnChanges() {
        reactOnChanges = true;
    }

    /**
     * Gibt an, dass bei Veränderungen der Caretposition der sichtbare Bereich nicht angepasst
     * werden soll.
     */
    @Override
    public void doNotReactOnChanges() {
        reactOnChanges = false;
    }

    /**
     * Forwards the <code>scrollRectToVisible()</code> message to the <code>JComponent</code>'s
     * parent. Components that can service the request, such as <code>JViewport</code>, override
     * this method and perform the scrolling.
     *
     * @param aRect
     *            the visible <code>Rectangle</code>
     * @see JViewport
     */
    @Override
    public void scrollRectToVisible(Rectangle aRect) {
        if (reactOnChanges) {
            super.scrollRectToVisible(aRect);
        }
    }

}
