Mercurial > hg > accesspd
diff java/src/uk/ac/qmul/eecs/ccmi/simpletemplate/Model.java @ 0:78b7fc5391a2
first import, outcome of NIME 2014 hackaton
author | Fiore Martin <f.martin@qmul.ac.uk> |
---|---|
date | Tue, 08 Jul 2014 16:28:59 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java/src/uk/ac/qmul/eecs/ccmi/simpletemplate/Model.java Tue Jul 08 16:28:59 2014 +0100 @@ -0,0 +1,405 @@ +/* + CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool + + Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +package uk.ac.qmul.eecs.ccmi.simpletemplate; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.ResourceBundle; + +/* + * The Wizard Model holds all the data the user enters during the process of creating a diagram template. + * Such data can be re-edited by the user during the same process or if they want to create + * a new diagram template out of an existing one. When the user has entered all the data the model is used + * to create an instance of the {@link Diagram class} which is then used as a prototype diagram. + * Diagram instances that the user will edit are created by cloning the relating prototype diagram. + * + */ +class Model { + Model(){ + diagramName = new Record(); + nodes = new ModelMap<Node>(); + edges = new ModelMap<Edge>(); + } + + @Override + public String toString(){// FIXME need to port the strings to the .properties file + StringBuilder builder = new StringBuilder(); + builder.append("Diagram Name is ").append(diagramName.value).append(".\n\n"); + builder.append(diagramName.value + " diagram has "+ (nodes.isEmpty() ? "no" : nodes.size()) + " node"+((nodes.size() == 1) ? "" : "s")); + if(!nodes.isEmpty()){ + builder.append(": "); + int i = 0; + for(Node n : nodes.values()){ + builder.append(n.type.value); + if(nodes.values().size() == 1) + break; + if(i == nodes.values().size() - 2){ + builder.append(" and "); + }else if(i < nodes.values().size()-1){ + builder.append(", "); + } + i++; + } + } + builder.append(".\n"); + for(Node n : nodes.values()){ + builder.append(n.type+" node has a ") + .append(n.shape + " shape.\n"); + builder.append(n.type+" node has "+ (n.properties.isEmpty() ? "no" : n.properties.size())+((n.properties.size() == 1) ? " property" : " properties")); + if(!n.properties.isEmpty()){ + builder.append(": "); + int i = 0; + for(Property p : n.properties.values()){ + builder.append(p.type.value); + if(n.properties.size() == 1) + break; + if(i == n.properties.size() - 2){ + builder.append(" and "); + }else if(i < n.properties.size()-1){ + builder.append(", "); + } + i++; + } + } + builder.append(".\n"); + for(Property p : n.properties.values()){ + builder.append(p.type+" property has position "+p.position); + if(p.position.value.equals(SimpleShapeNode.Position.Outside.toString())) + builder.append(" and shape "+p.shape+".\n"); + else + builder.append(".\n"); + builder.append(p.type+" property has "+(p.modifiers.isEmpty() ? "no" : p.modifiers.size())+(p.modifiers.size() == 1 ? " modifier" : " modifiers")); + if(!p.modifiers.isEmpty()){ + builder.append(": "); + int i = 0; + for(Modifier m : p.modifiers.values()){ + builder.append(m.type.value); + if(p.modifiers.size() == 1) + break; + if(i == p.modifiers.size() - 2){ + builder.append(" and "); + }else if(i < p.modifiers.size()-1){ + builder.append(", "); + } + i++; + } + } + builder.append(".\n"); + for(Modifier m : p.modifiers.values()){ + builder.append(m.type+ " modifier "); + if(m.format.values.length > 0) + builder.append("is formatted as "+m.format+".\n"); + else + builder.append("\n"); + } + } + } + builder.append('\n'); + builder.append(diagramName.value + " diagram has "+ (edges.isEmpty() ? "no" : edges.size()) + " edge"+((edges.size() == 1) ? "" : "s")); + if(!edges.isEmpty()){ + builder.append(": "); + int i = 0; + for(Edge e : edges.values()){ + builder.append(e.type.value); + if(edges.values().size() == 1) + break; + if(i == edges.values().size() - 2){ + builder.append(" and "); + }else if(i < edges.values().size()-1){ + builder.append(", "); + } + i++; + } + } + builder.append(".\n"); + for(Edge e : edges.values()){ + builder.append(e.type+ " edge has minimum nodes "+e.minNodes+" and maximum nodes "+e.maxNodes+".\n") + .append(e.type+ " edge has a "+ e.lineStyle+" line style.\n") + .append(e.type+" edge has "+ ((e.arrowHeads.values.length == 0) ? "no harrow heads.\n" : e.arrowHeads.values.length +" harrow heads: "+e.arrowHeads+".\n")); + } + builder.append('\n'); + builder.append("Press up and down arrow keys to go through the summary.\n"); + return builder.toString(); + } + + Record diagramName; + /* these are sets as when we edit an already existing node we just add */ + /* to the set the new node and it gets replaced */ + ModelMap<Node> nodes; + ModelMap<Edge> edges; + + static Element copy(Element src, Element dest){ + if(src instanceof Node){ + copy((Node)src,(Node)dest); + }else if (src instanceof Edge){ + copy((Edge)src,(Edge)dest); + }else if(src instanceof Property){ + copy((Property)src,(Property)dest); + }else{ + copy((Modifier)src,(Modifier)dest); + } + return dest; + } + + static void copy(Node src, Node dest){ + dest.id = src.id; + dest.type.value = src.type.value; + dest.shape.value = src.shape.value; + dest.properties.clear(); + dest.properties.putAll(src.properties); + } + + static void copy(Property src, Property dest){ + dest.id = src.id; + dest.type.value = src.type.value; + dest.shape.value = src.shape.value; + dest.position.value = src.position.value; + dest.modifiers.clear(); + dest.modifiers.putAll(src.modifiers); + } + + static void copy(Edge src, Edge dest){ + dest.id = src.id; + dest.type.value = src.type.value; + dest.lineStyle.value = src.lineStyle.value; + dest.maxNodes.value = src.maxNodes.value; + dest.minNodes.value = src.minNodes.value; + dest.arrowHeads.values = src.arrowHeads.values; + dest.arrowHeadsDescriptions.values = src.arrowHeadsDescriptions.values; + } + + static void copy(Modifier src, Modifier dest){ + dest.id = src.id; + dest.type.value = src.type.value; + dest.format.values = src.format.values; + dest.affix.values = src.affix.values; + } + + static class Record{ + Record(){ + value = ""; + } + Record(String value){ + this.value = value; + } + @Override + public String toString(){ + return value; + } + String value; + } + + static class StrArrayRecord{ + String [] values; + StrArrayRecord(){ + values = new String[0]; + } + + StrArrayRecord(String[] values){ + this.values = values; + } + + @Override + public String toString(){ + StringBuilder builder = new StringBuilder(); + for(int i=0; i<values.length; i++){ + builder.append(values[i]); + if(values.length == 1) + break; + if(i == values.length - 2) + builder.append(" and "); + else if(i < values.length -1 ) + builder.append(", "); + } + return builder.toString(); + } + } + + private static long uniqueId = 0; + static class Element { + Element(){ + type = new Record(); + id = uniqueId++; + } + + void clear () { + type.value = ""; + id = uniqueId++; + } + long id; + Record type; + } + + static class Node extends Element{ + Node(){ + shape = new Record(); + properties = new ModelMap<Property>(); + } + + @Override + void clear(){ + super.clear(); + shape.value = ""; + properties.clear(); + } + Record shape; + ModelMap<Property> properties; + } + + static class Edge extends Element { + Edge(){ + lineStyle = new Record(); + minNodes = new Record(); + maxNodes = new Record(); + arrowHeads = new StrArrayRecord(){ + @Override + public String toString(){ + StringBuilder builder = new StringBuilder(); + for(int i=0; i<values.length; i++){ + builder.append(values[i]+" with label "+arrowHeadsDescriptions.values[i]); + if(values.length == 1) + break; + if(i == values.length - 2) + builder.append(" and "); + else if(i < values.length -1 ) + builder.append(", "); + } + return builder.toString(); + } + }; + arrowHeadsDescriptions = new StrArrayRecord(); + } + @Override + public void clear(){ + super.clear(); + lineStyle.value = ""; + minNodes.value = ""; + maxNodes.value = ""; + arrowHeads.values = new String[0]; + arrowHeadsDescriptions.values = new String[0]; + } + Record lineStyle; + Record minNodes; + Record maxNodes; + StrArrayRecord arrowHeads; + StrArrayRecord arrowHeadsDescriptions; + } + + static class Property extends Element{ + Property(){ + position = new Model.Record(); + shape = new Model.Record(); + modifiers = new ModelMap<Modifier>(); + } + Record position; + Record shape; + ModelMap<Modifier> modifiers; + + @Override + void clear(){ + super.clear(); + modifiers.clear(); + position.value = ""; + shape.value = ""; + } + } + + static class Modifier extends Element { + StrArrayRecord format; + StrArrayRecord affix; + + Modifier(){ + affix = new StrArrayRecord(); + format = new StrArrayRecord(){ + @Override + public String toString(){ + ResourceBundle resources = ResourceBundle.getBundle(SpeechWizardDialog.class.getName()); + StringBuilder builder = new StringBuilder(); + for(int i=0; i<values.length; i++){ + builder.append(values[i]); + if(values[i].equals(resources.getString("modifier.format.prefix")) && !affix.values[0].isEmpty()){ + builder.append(' ').append(affix.values[0]); + } + if(values[i].equals(resources.getString("modifier.format.suffix")) && !affix.values[1].isEmpty()){ + builder.append(' ').append(affix.values[1]); + } + + if(values.length == 1) + break; + if(i == values.length - 2) + builder.append(" and "); + else if(i < values.length -1 ) + builder.append(", "); + } + return builder.toString(); + } + }; + + /* affix is always length = 2 as it only contains prefix and suffix string */ + /* eventually it contains empty strings but its length is not variable */ + affix.values = new String[2]; + } + + @Override + void clear(){ + super.clear(); + format.values = new String[0]; + affix.values = new String[2]; + } + } +} + + +@SuppressWarnings("serial") +class ModelMap<T extends Model.Element> extends LinkedHashMap<Long,T> { + public ModelMap(){ + namesMap = new LinkedHashMap<Long,String>(); + } + + @Override + public void clear(){ + namesMap.clear(); + super.clear(); + } + + public T put(Long key, T value){ + namesMap.put(key, value.type.value); + return super.put(key, value); + } + + public void putAll(Map<? extends Long,? extends T> m){ + for(Map.Entry<? extends Long,? extends T> entry : m.entrySet()){ + namesMap.put(entry.getKey(), entry.getValue().type.value); + } + super.putAll(m); + } + + public T remove(Object key){ + namesMap.remove(key); + return super.remove(key); + } + + public Collection<String> getNames(){ + return namesMap.values(); + } + + private Map<Long,String> namesMap; +}