Обычно функции отмены / возврата выполняются путем реализации стека. Вы можете реализовать свой собственный стек действий, который отслеживает предыдущие действия X, которые вы можете просто выталкивать каждый раз, когда пользователь отменяет действие. Вам, вероятно, также понадобится сохранить подобный тип структуры для функциональности повтора. Поэтому, когда действие извлекается из стека отмены, оно сначала должно перейти в стек отмены.
Если вы используете Java и NetBeans (хотя, строго говоря, вам не нужно использовать IDE NetBeans), вы можете взглянуть на платформу NetBeans (можно загрузить отдельно). Я не много работал с отменой / повтором, но он действительно обеспечивает функциональность.
Лично я бы просто написал класс, который включает любое «действие», которое может выполнить пользователь, что, как я вижу, вы уже сделали. Теперь это просто вопрос реализации стека для отслеживания этих действий, и когда кто-то извлекается из стека отмены, вам нужно сделать «противоположность» действию. Поместите элемент в стек повторного выполнения, поэтому, когда пользователь нажимает кнопку «Повторить», вы можете просто вытолкнуть действие из стека повторного выполнения и позволить приложению обработать его, как обычно.