package de.duehl.swing.ui.dragndrop;

/*
 * Copyright 2024 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.Component;
import java.awt.KeyboardFocusManager;

import javax.swing.text.JTextComponent;

/**
 * Diese Klasse dient dazu, bei einer Gui, die per EditorUiElementManager auf Änderungen überwacht
 * wird, bei der Aktualisierung der Daten nicht den Cursor im aktiven Text-Feld zu verlieren,
 * da beim langsamen Tippen sonst der Cursor verspringt.
 *
 * @version 1.01     2024-06-10
 * @author Christian Dühl
 */

public class TextComponentCaretPositionRestorer {

    private boolean oldPositionAvailable;
    private int oldCaretPosition;
    private JTextComponent textComponent;
    private int oldSelectionStart;
    private int oldSelectionEnd;

    public TextComponentCaretPositionRestorer() {
        oldPositionAvailable = false;
        oldCaretPosition = -1;
        textComponent = null;
        oldSelectionStart = -1;
        oldSelectionEnd = -1;

        detectActualFocusOwner();
    }

    private void detectActualFocusOwner() {
        boolean componentFound = false;
        Component owner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
        if (owner instanceof JTextComponent textComponent) {
            componentFound = true;
            this.textComponent = textComponent;
        }

        if (componentFound) {
            oldPositionAvailable = true;
            oldCaretPosition = textComponent.getCaretPosition();
            oldSelectionStart = textComponent.getSelectionStart();
            oldSelectionEnd = textComponent.getSelectionEnd();
        }
    }

    public void restoreCaretPosition() {
        if (oldPositionAvailable) {
            /*
             * Falls der Text nun kürzer ist, müssen wir das anpassen!
             * Ansonsten fliegt eine Ausnahme, wenn man das letzte Zeichen löscht.
             */
            int maxCaretPosition = textComponent.getText().length();
            if (oldCaretPosition > maxCaretPosition) {
                oldCaretPosition = maxCaretPosition;
            }

            textComponent.setCaretPosition(oldCaretPosition);

            if (oldSelectionStart < maxCaretPosition) {
                int selectionStart = oldSelectionStart;
                int selectionEnd = oldSelectionEnd;
                if (selectionEnd > maxCaretPosition) {
                    selectionEnd = maxCaretPosition;
                }
                textComponent.setSelectionStart(selectionStart);
                textComponent.setSelectionEnd(selectionEnd);
            }
        }
    }

}
