Cursor.java from gzz at Krugle
Show Cursor.java syntax highlighted
/*
Cursor.java
*
* Copyright (c) 2003 Benja Fallenstein
*
* This file is part of Gzz.
*
* Gzz is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Gzz 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 Lesser General
* Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with Gzz; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*/
/*
* Written by Benja Fallenstein
*/
package gzz.loom;
import java.util.*;
import com.hp.hpl.mesa.rdf.jena.model.*;
/** A Loom cursor position in an RDF graph.
* Currently a focus and a rotation, as handed to a view.
* Not stored in the structure.
*/
public class Cursor {
/** The focused node, usually shown in the middle of the screen.
* "Where you are."
*/
public Resource focus;
/** Index of the selection, "where you go next". 0 is the index in the
* middle, or one smaller if there are an even number of choices.
*/
public int rotation;
/** The comparator used to order the nodes in the graph.
* The vertical order of nodes is determined by this Comparator.
*/
public Comparator order;
/** Create a new cursor without giving it a position yet.
*/
public Cursor(Comparator order) {
this.order = order;
}
/** Create a new cursor and give it a position.
*/
public Cursor(Comparator order, Resource focus, int dir,
RDFNode rotation) {
this(order);
set(focus, dir, rotation);
}
/** Set the position of the cursor without setting a rotation.
*/
public void set(Resource focus) {
this.focus = focus;
this.rotation = 0;
}
/** Set the position of the cursor.
* Ambiguity of <code>rotation</code> (is it posward
* or negward?) might be a problem?
*/
public void set(Resource focus, int dir, RDFNode rotation) {
this.focus = focus;
SortedSet set = getConnections(dir);
if(!set.contains(rotation))
throw new NoSuchElementException("Rotation: "+rotation);
this.rotation = set.headSet(rotation).size()-(set.size()-1)/2;
}
/** Get <code>rotation</code> from the middle connection.
* E.g., when there are 6 connections and the second one is selected,
* <code>rotation</code> is -1.
*/
public int getRotation() {
return rotation;
}
/** The posward or negward connections of <code>focus</code> to show,
* in order. XXX refactor-- we need only a subset of all properties,
* and recursion... currently slow because we iterate though
* ALL triples in the graph.
*/
public SortedSet getConnections(int dir) {
try {
SortedSet nodes = new TreeSet(order);
StmtIterator i = focus.getModel().listStatements();
for(; i.hasNext();) {
Statement stmt = i.next();
if(dir < 0) {
if(stmt.getObject().equals(focus))
nodes.add(stmt.getSubject());
} else {
if(stmt.getSubject().equals(focus))
nodes.add(stmt.getObject());
}
}
i.close();
return nodes;
} catch(RDFException e) {
throw new Error("RDFException: "+e);
}
}
/** Rotate the view up or down.
* This moves the rotation of the cursor up or down.
*/
public void rotate(int dir) {
SortedSet
neg = getConnections(-1),
pos = getConnections(1);
int negn = neg.size();
int posn = pos.size();
int n = (negn>posn) ? negn : posn;
int abs = (n-1)/2 + rotation + dir;
if(abs<0 || abs>=n)
return;
rotation += dir;
}
/** Get the index of the rotation in the list of
* left/right connections. Can be out-of-bounds in that
* it is smaller than zero or larger than the number
* of items in the list: e.g. if you have 11 nodes
* connected to the right and 3 nodes connected
* to the left, when the last of the 11 nodes is selected,
* getRotationIndex(-1) will return +7. XXX
*/
public int getRotationIndex(int dir) {
int n = getConnections(dir).size();
int abs = (n-1)/2 + rotation;
return abs;
}
/** Get the selected node in the given direction.
* getRotationNode(1) is the node we go to if
* we hit 'Right.' getRotationNode(-1) is the node
* we go to if we hit 'Left.' getRotationNode(0)
* is the focused node.
*/
public RDFNode getRotationNode(int dir) {
if(dir == 0)
return focus;
Iterator iter = getConnections(dir).iterator();
int n = getRotationIndex(dir);
if(n < 0)
// nothing there
return null;
for(int i=0; i<n; i++) if(iter.hasNext()) iter.next();
if(!iter.hasNext())
// nothing there
return null;
return (RDFNode)iter.next();
}
/** Move left/right. XXX
*/
public void move(int dir) {
RDFNode node = getRotationNode(dir);
if(node == null || !(node instanceof Resource)) return;
set((Resource)node, -dir, focus);
}
}
See more files for this project here