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: }