Наши партнеры

UnixForum



  • Здесь
  • купить жижу для вейпа
  • gosmoke.ru


Библиотека сайта rus-linux.net

Фреймворк Violet

Глава 22 из книги "Архитектура приложений с открытым исходным кодом", том 1.

Оригинал: "Violet", глава из книги "The Architecture of Open Source Applications"
Автор: Cay Horstmann
Перевод: Н.Ромоданов

22.8. Операции Undo/Redo

Реализация множественных операций undo/redo кажется сложной задачей, но в пакете Swing undo ([Top00], глава 9) приведены хорошие рекомендации, относящиеся к архитектуре. Менеджер UndoManager управляет стеком объектов UndoableEdit. В каждом из них есть метод undo, который отменяет эффект операции редактирования, и метод redo, который отменяет действие undo (то есть, восстанавливает первоначальную операцию редактирования). CompoundEdit представляет собой последовательность операций UndoableEdit, которые должны отменяться или восстанавливаться в полном объеме. Вам предлагается определить небольшие, атомарные операции редактирования (например, добавление или удаление одного ребра или узла в случае использования графа), которые, по мере необходимости, группируются в составные операции редактирования.

Задача состоит в том, чтобы определить небольшой набор атомарных операций, каждую из которых можно легко отменить. В Violet это следующие операции:

  • добавление или удаление узла или ребра
  • подсоединение или отсоединение потомка узла
  • перемещение узла
  • изменения свойств узла или ребра

Для каждой их этих операций есть понятное действие отмены undo. Например, операция undo для добавления узла является удалением узла. Операция undo для перемещения узла означает перемещение в обратном направлении.

Рис.22.6: Операция Undo должна отменять структурные изменения, сделанные в модели

Отметим, что эти атомарные операции не совпадают с действиями в пользовательском интерфейсе или с методами интерфейса Graph, которые вызываются с помощью действий пользовательского интерфейса. Например, рассмотрим диаграмму последовательности на рисунке 22.6, и предположим, что пользователь перетаскивает вправо с помощью мыши блок активации. При отпускании кнопки мыши, вызывается метод:

public boolean addEdgeAtPoints(Edge e, Point2D p1, Point2D p2)

Этот метод добавляет ребро, но может также осуществлять другие операции, которые указываются в подклассах Edge и Node. В этом случае блок активации будет добавлен к линии, расположенной справа. При выполнении операции отмены undo нужно также будет удалить блок активация. Таким образом, в модели (в нашем случае в графе) должны записываться структурные изменения, которые могут быть отменены. Для этого недостаточно пользоваться только контроллером операций.

Как предусмотрено в пакете Swing undo, классы graph, node и edge должны всякий раз, когда происходит структурное изменение, посылать уведомления UndoableEditEvent в менеджер уведомлений UndoManager. В Violet используется более общая схема, в которой граф сам управляет методами - слушателями (listeners) следующего интерфейса:

public interface GraphModificationListener
{
  void nodeAdded(Graph g, Node n);
  void nodeRemoved(Graph g, Node n);
  void nodeMoved(Graph g, Node n, double dx, double dy);
  void childAttached(Graph g, int index, Node p, Node c);
  void childDetached(Graph g, int index, Node p, Node c);
  void edgeAdded(Graph g, Edge e);
  void edgeRemoved(Graph g, Edge e);
  void propertyChangedOnNodeOrEdge(Graph g, PropertyChangeEvent event);
}

Фреймворк устанавливает слушателя в каждом графе; такой слушатель является мостиком к менеджеру операций undo. Чтобы поддерживать операцию undo, нужно дополнительно переопределить общую поддержку слушателей модели — операции, выполняемые с графом, должны непосредственно взаимодействовать с менеджером undo. Но мне бы также хотелось поддерживать совместимые экспериментальные функции редактирования.

Если вы хотите поддерживать операции undo/redo в вашем приложении, подумайте внимательно об атомарных операциях в модели (а не вашего пользовательского интерфейса). Когда в модели происходят структурные изменения, должны вырабатываться события и менеджер Swing undo должен собирать и группировать такие события.


Продолжение статьи: 22.9. Архитектура плагинов.