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.Map; 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 Map<Long, TopicViewmodel> topics; 028 private Map<Long, AssociationViewmodel> assocs; 029 030 private Logger logger = Logger.getLogger(getClass().getName()); 031 032 // ---------------------------------------------------------------------------------------------------- Constructors 033 034 public TopicmapViewmodel(TopicModel topicmapTopic, Map<Long, TopicViewmodel> topics, 035 Map<Long, AssociationViewmodel> assocs) { 036 this.topicmapTopic = topicmapTopic; 037 this.topics = topics; 038 this.assocs = assocs; 039 } 040 041 // -------------------------------------------------------------------------------------------------- Public Methods 042 043 public long getId() { 044 return topicmapTopic.getId(); 045 } 046 047 // --- 048 049 public Iterable<TopicViewmodel> getTopics() { 050 return topics.values(); 051 } 052 053 public Iterable<AssociationViewmodel> getAssociations() { 054 return assocs.values(); 055 } 056 057 // --- 058 059 public TopicViewmodel getTopic(long id) { 060 return topics.get(id); 061 } 062 063 public AssociationViewmodel getAssociation(long id) { 064 return assocs.get(id); 065 } 066 067 // --- 068 069 @Override 070 public JSONObject toJSON() { 071 try { 072 JSONObject topicmap = new JSONObject(); 073 topicmap.put("info", topicmapTopic.toJSON()); 074 topicmap.put("topics", DeepaMehtaUtils.objectsToJSON(topics.values())); 075 topicmap.put("assocs", DeepaMehtaUtils.objectsToJSON(assocs.values())); 076 return topicmap; 077 } catch (Exception e) { 078 throw new RuntimeException("Serialization failed (" + this + ")", e); 079 } 080 } 081 082 @Override 083 public String toString() { 084 return "topicmap " + getId(); 085 } 086 087 // -------------------------------------------------------------------------------------------- Public Inner Classes 088 089 // Note: there is a client-side equivalent in canvas_view.js (deepamehta-webclient plugin) 090 public class GridPositioning { 091 092 // Settings 093 private final int GRID_DIST_X = 220; // MAX_TOPIC_LABEL_WIDTH + 20 pixel padding 094 private final int GRID_DIST_Y = 80; 095 private final int START_X; 096 private final int START_Y = 50; 097 private final int MIN_Y = -9999; 098 099 private final int canvasWidth; 100 private final int transX; 101 102 private int gridX; 103 private int gridY; 104 105 // --- Constructors --- 106 107 public GridPositioning(int canvasWidth, int transX) { 108 this.canvasWidth = canvasWidth; 109 this.transX = transX; 110 START_X = 50 - transX; 111 // 112 Point startPos = findStartPostition(); 113 gridX = startPos.x; 114 gridY = startPos.y; 115 } 116 117 // --- Public Methods --- 118 119 public Point nextPosition() { 120 Point pos = new Point(gridX, gridY); 121 advancePosition(); 122 return pos; 123 } 124 125 // --- Private Methods --- 126 127 private Point findStartPostition() { 128 int maxY = MIN_Y; 129 for (TopicViewmodel topic : topics.values()) { 130 if (topic.getY() > maxY) { 131 maxY = topic.getY(); 132 } 133 } 134 int x = START_X; 135 int y = maxY != MIN_Y ? maxY + GRID_DIST_Y : START_Y; 136 return new Point(x, y); 137 } 138 139 private void advancePosition() { 140 if (gridX + GRID_DIST_X + transX > canvasWidth) { 141 gridX = START_X; 142 gridY += GRID_DIST_Y; 143 } else { 144 gridX += GRID_DIST_X; 145 } 146 } 147 } 148 }