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    }