001 package de.deepamehta.plugins.topicmaps.model;
002
003 import de.deepamehta.core.JSONEnabled;
004 import de.deepamehta.core.model.TopicModel;
005 import de.deepamehta.core.util.DeepaMehtaUtils;
006
007 import org.codehaus.jettison.json.JSONObject;
008
009 import java.awt.Point;
010
011 import java.util.List;
012 import java.util.logging.Logger;
013
014
015
016 /**
017 * A topicmap viewmodel: a collection of topics and associations plus their view properties.
018 * <p>
019 * Features:
020 * - Serialization to JSON.
021 */
022 public class TopicmapViewmodel implements JSONEnabled {
023
024 // ---------------------------------------------------------------------------------------------- Instance Variables
025
026 private TopicModel topicmapTopic;
027 private List<TopicViewmodel> topics;
028 private List<AssociationViewmodel> assocs;
029
030 private Logger logger = Logger.getLogger(getClass().getName());
031
032 // ---------------------------------------------------------------------------------------------------- Constructors
033
034 public TopicmapViewmodel(TopicModel topicmapTopic, List<TopicViewmodel> topics, List<AssociationViewmodel> assocs) {
035 this.topicmapTopic = topicmapTopic;
036 this.topics = topics;
037 this.assocs = assocs;
038 }
039
040 // -------------------------------------------------------------------------------------------------- Public Methods
041
042 public long getId() {
043 return topicmapTopic.getId();
044 }
045
046 // ---
047
048 public Iterable<TopicViewmodel> getTopics() {
049 return topics;
050 }
051
052 public Iterable<AssociationViewmodel> getAssociations() {
053 return assocs;
054 }
055
056 // ---
057
058 @Override
059 public JSONObject toJSON() {
060 try {
061 JSONObject topicmap = new JSONObject();
062 topicmap.put("info", topicmapTopic.toJSON());
063 topicmap.put("topics", DeepaMehtaUtils.objectsToJSON(topics));
064 topicmap.put("assocs", DeepaMehtaUtils.objectsToJSON(assocs));
065 return topicmap;
066 } catch (Exception e) {
067 throw new RuntimeException("Serialization failed (" + this + ")", e);
068 }
069 }
070
071 @Override
072 public String toString() {
073 return "topicmap " + getId();
074 }
075
076 // -------------------------------------------------------------------------------------------- Public Inner Classes
077
078 // Note: there is a client-side equivalent in canvas_view.js (deepamehta-webclient plugin)
079 public class GridPositioning {
080
081 // Settings
082 private final int GRID_DIST_X = 220; // MAX_TOPIC_LABEL_WIDTH + 20 pixel padding
083 private final int GRID_DIST_Y = 80;
084 private final int START_X;
085 private final int START_Y = 50;
086 private final int MIN_Y = -9999;
087
088 private final int canvasWidth;
089 private final int transX;
090
091 private int gridX;
092 private int gridY;
093
094 // --- Constructors ---
095
096 public GridPositioning(int canvasWidth, int transX) {
097 this.canvasWidth = canvasWidth;
098 this.transX = transX;
099 START_X = 50 - transX;
100 //
101 Point startPos = findStartPostition();
102 gridX = startPos.x;
103 gridY = startPos.y;
104 }
105
106 // --- Public Methods ---
107
108 public Point nextPosition() {
109 Point pos = new Point(gridX, gridY);
110 advancePosition();
111 return pos;
112 }
113
114 // --- Private Methods ---
115
116 private Point findStartPostition() {
117 int maxY = MIN_Y;
118 for (TopicViewmodel topic : topics) {
119 if (topic.getY() > maxY) {
120 maxY = topic.getY();
121 }
122 }
123 int x = START_X;
124 int y = maxY != MIN_Y ? maxY + GRID_DIST_Y : START_Y;
125 return new Point(x, y);
126 }
127
128 private void advancePosition() {
129 if (gridX + GRID_DIST_X + transX > canvasWidth) {
130 gridX = START_X;
131 gridY += GRID_DIST_Y;
132 } else {
133 gridX += GRID_DIST_X;
134 }
135 }
136 }
137 }