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