Рейтинг@Mail.ru
[Войти] [Зарегистрироваться]

Наши друзья и партнеры

UnixForum
Беспроводные выключатели nooLite купить дешевый 
компьютер родом из Dhgate.com

Lines Club

Ищем достойных соперников.

Библиотека сайта или "Мой Linux Documentation Project"

Фреймворк Violet

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

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

22.2. Графический фреймворк

Violet базируется на универсальном фреймворке редактирования графов, который может выдавить изображения и позволяет редактировать узлы и ребра изображений произвольной формы. Редактор Violet для UML использует узлы для отображения классов, объектов, границ активации (в диаграммах последовательностей), и так далее, а ребра — для различных дуг в диаграммах UML. Другой экземпляр графического фреймворка может отображать диаграммы «сущность - отношение» или синтаксические диаграммы.

Рис.22.2: Простой экземпляр фреймворка редактирования

Для того чтобы проиллюстрировать фреймворк, рассмотрим редактор для очень простых графов с черно-белыми круглыми узлами и прямыми ребрами (рис.22.2). В классе SimpleGraph определяются прототипные объекты для типов узлов и ребер, иллюстрирующие шаблон прототипорования prototype:

public class SimpleGraph extends AbstractGraph
{
  public Node[] getNodePrototypes()
  {
    return new Node[]
    {
      new CircleNode(Color.BLACK),
      new CircleNode(Color.WHITE)
    };
  }
  public Edge[] getEdgePrototypes()
  {
    return new Edge[]
    {
      new LineEdge()
    };
  }
}

Прототипные объекты используются для рисования кнопок узлов и ребер в верхней части рисунка 22.2. Они клонируются всякий раз, когда пользователь добавляет в граф новый экземпляр узла или ребра. Узел Node и ребро Edge являются интерфейсами со следующими ключевыми методами:

  • В обоих интерфейсах есть метод getShape, который возвращает объект Java2D Shape, представляющий собой узел или ребро.
  • The интерфейс Edge имеет методы, с помощью которых можно получить начальный и конечный узел ребра.
  • Метод getConnectionPoint в интерфейсе типа Node вычисляет оптимальные точки подсоединения к границе узла (смотрите рис.22.3).
  • Метод getConnectionPoints интерфейса Edge позволяет получать две конечные точки ребра. Этот метод необходим, чтобы рисовать «грабберы», которыми помечается текущее выбранное ребро.
  • Узел может иметь потомков, которые перемещаются вместе с родителем. Предлагается ряд методов для нумерации и управления потомками.

Рис.22.3: Поиск точки присоединения на границе формы узла Node

Удобные классы AbstractNode и AbstractEdge реализуют ряд таких методов, а классы RectangularNode и SegmentedLineEdge обеспечивают всю полную реализацию прямоугольных узлов со строкой-заголовком и ребрами, которые состоят из отрезков прямой.

В случае нашего простого редактора графов нам нужны подклассы CircleNode и LineEdge, в которых есть метод draw, метод contains и метод getConnectionPoint, в которых описывается форма границы узла. Ниже приведен код, а на рис 22,4 показана диаграмма классов для этих классов (нарисованных, конечно, с помощью Violet).

public class CircleNode extends AbstractNode
{
  public CircleNode(Color aColor)
  {
    size = DEFAULT_SIZE;
    x = 0;
    y = 0;
    color = aColor;
  }

  public void draw(Graphics2D g2)
  {
    Ellipse2D circle = new Ellipse2D.Double(x, y, size, size);
    Color oldColor = g2.getColor();
    g2.setColor(color);
    g2.fill(circle);
    g2.setColor(oldColor);
    g2.draw(circle);
  }

  public boolean contains(Point2D p)
  {
    Ellipse2D circle = new Ellipse2D.Double(x, y, size, size);
    return circle.contains(p);
  }

  public Point2D getConnectionPoint(Point2D other)
  {
    double centerX = x + size / 2;
    double centerY = y + size / 2;
    double dx = other.getX() - centerX;
    double dy = other.getY() - centerY;
    double distance = Math.sqrt(dx * dx + dy * dy);
    if (distance == 0) return other;
    else return new Point2D.Double(
      centerX + dx * (size / 2) / distance,
      centerY + dy * (size / 2) / distance);
  }

  private double x, y, size, color;
  private static final int DEFAULT_SIZE = 20;
}

public class LineEdge extends AbstractEdge
{
  public void draw(Graphics2D g2)
  { g2.draw(getConnectionPoints()); }

  public boolean contains(Point2D aPoint)
  {
    final double MAX_DIST = 2;
    return getConnectionPoints().ptSegDist(aPoint) < MAX_DIST;
  }
}

Рис.22.4: Диаграмма классов для простого графа

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

Конечно, есть и другие графовые фреймворки, например, JGraph [Ald02] и JUNG2. Однако эти фреймворки гораздо более сложные и они являются фреймворками для рисования графов, а не для создания приложений, которые рисуют графы.


Продолжение статьи: 22.3. Использование свойств JavaBeans.


Эта статья еще не оценивалась
Вы сможете оценить статью и оставить комментарий, если войдете или зарегистрируетесь.
Только зарегистрированные пользователи могут оценивать и комментировать статьи.

Комментарии отсутствуют