fiore@3: /* fiore@3: CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool fiore@3: fiore@3: Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) fiore@3: fiore@3: This program is free software: you can redistribute it and/or modify fiore@3: it under the terms of the GNU General Public License as published by fiore@3: the Free Software Foundation, either version 3 of the License, or fiore@3: (at your option) any later version. fiore@3: fiore@3: This program is distributed in the hope that it will be useful, fiore@3: but WITHOUT ANY WARRANTY; without even the implied warranty of fiore@3: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the fiore@3: GNU General Public License for more details. fiore@3: fiore@3: You should have received a copy of the GNU General Public License fiore@3: along with this program. If not, see . fiore@3: */ fiore@3: package uk.ac.qmul.eecs.ccmi.diagrammodel; fiore@3: fiore@3: import java.util.ArrayList; fiore@3: import java.util.Collections; fiore@3: import java.util.List; fiore@3: fiore@3: import javax.swing.tree.DefaultMutableTreeNode; fiore@3: fiore@3: /** fiore@3: * This class represent a general node in a TreeModel fiore@3: * fiore@3: */ fiore@3: @SuppressWarnings("serial") fiore@3: public abstract class DiagramTreeNode extends DefaultMutableTreeNode { fiore@3: /** fiore@3: * Creates a tree node with the default user object. The default user object has no label. Therefore fiore@3: * this node will have no label when displayed on a tree. fiore@3: */ fiore@3: public DiagramTreeNode() { fiore@3: super(); fiore@3: notes = ""; fiore@3: userObject = new UserObject(); fiore@3: setSuperClassUserObject(userObject); fiore@3: bookmarkKeys = new ArrayList(); fiore@3: } fiore@3: fiore@3: /** fiore@3: * Creates a tree node, holding the user object passed as argument. The label of the fiore@3: * tree node will be the string returned by {@code userObject.toString()} fiore@3: * fiore@3: * @param userObject the user object for this tree node fiore@3: * fiore@3: * @see javax.swing.tree.DefaultMutableTreeNode fiore@3: */ fiore@3: public DiagramTreeNode(Object userObject) { fiore@3: this(); fiore@3: setUserObject(userObject); fiore@3: } fiore@3: fiore@3: /** fiore@3: * Each DiagramModelTreeNode keeps track of the bookmarks it has been assigned. Bookmarks fiore@3: * will affect how this tree node will be represented on a JTree: when a tree node is bookmarked fiore@3: * an apex appears at the right of its name. fiore@3: * fiore@3: * @param key the bookmark fiore@3: * @return true if this bookmark inner collection changed as a result of the call fiore@3: */ fiore@3: boolean addBookmarkKey(String key){ fiore@3: return bookmarkKeys.add(key); fiore@3: } fiore@3: fiore@3: /** fiore@3: * Removes a bookmark key from the inner collection. fiore@3: * fiore@3: * @param key the key to remove fiore@3: * @return true if this bookmark inner collection changed as a result of the call fiore@3: */ fiore@3: boolean removeBookmarkKey(String key){ fiore@3: return bookmarkKeys.remove(key); fiore@3: } fiore@3: fiore@3: /** fiore@3: * Returns the the bookmark keys currently associated to this tree node in the tree model. fiore@3: * fiore@3: * @return a n unmodifiable list of strings used as keys for bookmarks fiore@3: */ fiore@3: public List getBookmarkKeys(){ fiore@3: return Collections.unmodifiableList(bookmarkKeys); fiore@3: } fiore@3: fiore@3: public String getNotes(){ fiore@3: return notes; fiore@3: } fiore@3: fiore@3: /** fiore@3: * Set a note for this tree node. A Note is a text the user wants to attach to a tree node. Notes fiore@3: * will affect how this tree node will be represented on a JTree: when a tree node is assigned a note fiore@3: * a number sign (#) appears at the right of its name. fiore@3: * fiore@3: * @param note the text of the note fiore@3: * @param source used by {@code DiagramElement} to trigger {@code ElementChangeEvents} fiore@3: * fiore@3: * @see DiagramElement#setNotes(String, Object) fiore@3: */ fiore@3: protected void setNotes(String note, Object source){ fiore@3: this.notes = note; fiore@3: } fiore@3: fiore@3: @Override fiore@3: public DiagramTreeNode getParent(){ fiore@3: return (DiagramTreeNode)super.getParent(); fiore@3: } fiore@3: fiore@3: @Override fiore@3: public DiagramTreeNode getChildAt(int i){ fiore@3: return (DiagramTreeNode)super.getChildAt(i); fiore@3: } fiore@3: fiore@3: @Override fiore@3: public DiagramTreeNode getRoot(){ fiore@3: return (DiagramTreeNode)super.getRoot(); fiore@3: } fiore@3: fiore@3: @Override fiore@3: public void setUserObject(Object userObject){ fiore@3: ((UserObject)this.userObject).setObject(userObject); fiore@3: } fiore@3: fiore@3: @Override fiore@3: public Object getUserObject(){ fiore@3: return userObject; fiore@3: } fiore@3: fiore@3: /** fiore@3: * Return a String representing this object for this tree node in a way more suitable fiore@3: * for a text to speech synthesizer to read, than toString(). fiore@3: * fiore@3: * @return a String suitable for text to speech synthesis fiore@3: */ fiore@3: public String spokenText(){ fiore@3: return ((UserObject)userObject).spokenText(); fiore@3: } fiore@3: fiore@3: /** fiore@3: * Returns a more detailed description of the tree node than {@link #spokenText()}. fiore@3: * fiore@3: * @return a description of the tree node fiore@3: */ fiore@3: public String detailedSpokenText(){ fiore@3: return spokenText(); fiore@3: } fiore@3: fiore@3: /** fiore@3: * returns the tree node name "as it is", without any decoration such as notes, bookmarks or cardinality; fiore@3: * unlike the String returned by toString. fiore@3: * fiore@3: * @return the tree node name fiore@3: */ fiore@3: public String getName(){ fiore@3: return ((UserObject)userObject).getName(); fiore@3: } fiore@3: fiore@3: @Override fiore@3: public boolean isRoot(){ fiore@3: return false; // root node overwrites this method fiore@3: } fiore@3: fiore@3: @Override fiore@3: public DiagramTreeNode getLastLeaf() { fiore@3: return (DiagramTreeNode)super.getLastLeaf(); fiore@3: } fiore@3: fiore@3: @Override fiore@3: public DiagramTreeNode getNextLeaf() { fiore@3: return (DiagramTreeNode)super.getNextLeaf(); fiore@3: } fiore@3: fiore@3: @Override fiore@3: public DiagramTreeNode getNextNode() { fiore@3: return (DiagramTreeNode)super.getNextNode(); fiore@3: } fiore@3: fiore@3: @Override fiore@3: public DiagramTreeNode getNextSibling() { fiore@3: return (DiagramTreeNode)super.getNextSibling(); fiore@3: } fiore@3: fiore@3: @Override fiore@3: public DiagramTreeNode getPreviousLeaf() { fiore@3: return (DiagramTreeNode)super.getPreviousLeaf(); fiore@3: } fiore@3: fiore@3: @Override fiore@3: public DiagramTreeNode getPreviousNode() { fiore@3: return (DiagramTreeNode)super.getPreviousNode(); fiore@3: } fiore@3: fiore@3: @Override fiore@3: public DiagramTreeNode getPreviousSibling() { fiore@3: return (DiagramTreeNode)super.getPreviousSibling(); fiore@3: } fiore@3: fiore@3: private void setSuperClassUserObject(Object u){ fiore@3: super.setUserObject(u); fiore@3: } fiore@3: fiore@3: private UserObject getUserObjectInstance(){ fiore@3: return new UserObject(); fiore@3: } fiore@3: fiore@3: /** fiore@3: * The bookmarks, involving this node, entered by the user in the DiagramTree this node belongs to. fiore@3: */ fiore@3: protected List bookmarkKeys; fiore@3: /** fiore@3: * The notes set by the user for this node. fiore@3: */ fiore@3: protected String notes; fiore@3: /* hides the DefaultMutableTreeNode protected field */ fiore@3: private Object userObject; fiore@3: /** fiore@3: * The character that is appended to the label of this node when the user enters some notes for it. fiore@3: */ fiore@3: protected static final char NOTES_CHAR = '#'; fiore@3: /** fiore@3: * The character that is appended to the label of this node when it's bookmarked by the user. fiore@3: */ fiore@3: protected static final char BOOKMARK_CHAR = '\''; fiore@3: /** fiore@3: * The string that is appended to the spoken text of this node when the user enters some notes for it. fiore@3: * fiore@3: * @see #spokenText() fiore@3: */ fiore@3: protected static final String BOOKMARK_SPEAK = ", bookmarked"; fiore@3: /** fiore@3: * The string that is appended to the spoken text of this node when it's bookmarked by the user. fiore@3: * fiore@3: * @see #spokenText() fiore@3: */ fiore@3: protected static final String NOTES_SPEAK = ", has notes"; fiore@3: fiore@3: @Override fiore@3: public Object clone(){ fiore@3: DiagramTreeNode clone = (DiagramTreeNode )super.clone(); fiore@3: clone.notes = ""; fiore@3: clone.bookmarkKeys = new ArrayList(); fiore@3: clone.userObject = clone.getUserObjectInstance(); fiore@3: clone.setSuperClassUserObject(clone.userObject); fiore@3: return clone; fiore@3: } fiore@3: fiore@3: /* this works as a wrapper for the real user object in order to provide */ fiore@3: /* decoration on the treeNode label to signal and/or bookmarks */ fiore@3: private class UserObject { fiore@3: private Object object; fiore@3: fiore@3: public UserObject(){ fiore@3: object = ""; fiore@3: } fiore@3: public void setObject(Object o){ fiore@3: this.object = o; fiore@3: } fiore@3: fiore@3: @Override fiore@3: public boolean equals(Object o){ fiore@3: return this.object.equals(o); fiore@3: } fiore@3: fiore@3: @Override fiore@3: public String toString(){ fiore@3: StringBuilder builder = new StringBuilder(object.toString()); fiore@3: if(!"".equals(notes)){ fiore@3: builder.append(NOTES_CHAR); fiore@3: } fiore@3: if(!bookmarkKeys.isEmpty()) fiore@3: builder.append(BOOKMARK_CHAR); fiore@3: return builder.toString(); fiore@3: } fiore@3: fiore@3: public String spokenText(){ fiore@3: StringBuilder builder = new StringBuilder(object.toString()); fiore@3: if(!"".equals(notes)){ fiore@3: builder.append(NOTES_SPEAK); fiore@3: } fiore@3: if(!bookmarkKeys.isEmpty()) fiore@3: builder.append(BOOKMARK_SPEAK); fiore@3: return builder.toString(); fiore@3: } fiore@3: fiore@3: public String getName(){ fiore@3: return object.toString(); fiore@3: } fiore@3: } fiore@3: }