35 |
*/ |
*/ |
36 |
public class Cursor { |
public class Cursor { |
37 |
|
|
38 |
/** The focused node, usually shown in the middle of the screen. "Where you are." |
/** The focused node, usually shown in the middle of the screen. |
39 |
|
* "Where you are." |
40 |
*/ |
*/ |
41 |
public Resource focus; |
public Resource focus; |
42 |
|
|
43 |
/** The 'selected' node, left/right of the focused node. "Where you go." |
/** Index of the selection, "where you go next". 0 is the index in the |
44 |
* This can be either left or right of the focus. |
* middle, or one smaller if there are an even number of choices. |
45 |
*/ |
*/ |
46 |
public RDFNode rotation; |
public int rotation; |
|
|
|
|
/** The direction of the rotation from the focus: Posward (+1) or negward (-1). |
|
|
* If there is no rotation (rotation == null), this is zero. |
|
|
* The idea is that the same node can be right and left of the focus, |
|
|
* and we need to know which one's the rotation we're speaking about. |
|
|
*/ |
|
|
public int dir; |
|
47 |
|
|
48 |
/** The comparator used to order the nodes in the graph. |
/** The comparator used to order the nodes in the graph. |
49 |
* The vertical order of nodes is determined by this Comparator. |
* The vertical order of nodes is determined by this Comparator. |
50 |
*/ |
*/ |
51 |
public Comparator order; |
public Comparator order; |
52 |
|
|
53 |
|
/** Create a new cursor without giving it a position yet. |
54 |
|
*/ |
55 |
public Cursor(Comparator order) { |
public Cursor(Comparator order) { |
56 |
this.order = order; |
this.order = order; |
57 |
} |
} |
58 |
|
|
59 |
public Cursor(Comparator order, Resource focus, int dir, RDFNode rotation) { |
/** Create a new cursor and give it a position. |
60 |
|
*/ |
61 |
|
public Cursor(Comparator order, Resource focus, int dir, |
62 |
|
RDFNode rotation) { |
63 |
this(order); |
this(order); |
64 |
set(focus, dir, rotation); |
set(focus, dir, rotation); |
65 |
} |
} |
66 |
|
|
67 |
|
/** Set the position of the cursor without setting a rotation. |
68 |
|
*/ |
69 |
|
public void set(Resource focus) { |
70 |
|
this.focus = focus; |
71 |
|
this.rotation = 0; |
72 |
|
} |
73 |
|
|
74 |
|
/** Set the position of the cursor. |
75 |
|
* Ambiguity of <code>rotation</code> (is it posward |
76 |
|
* or negward?) might be a problem? |
77 |
|
*/ |
78 |
public void set(Resource focus, int dir, RDFNode rotation) { |
public void set(Resource focus, int dir, RDFNode rotation) { |
79 |
this.focus = focus; |
this.focus = focus; |
80 |
this.dir = dir; |
SortedSet set = getConnections(dir); |
81 |
this.rotation = rotation; |
if(!set.contains(rotation)) |
82 |
|
throw new NoSuchElementException("Rotation: "+rotation); |
83 |
|
|
84 |
|
this.rotation = set.headSet(rotation).size()-(set.size()-1)/2; |
85 |
} |
} |
86 |
|
|
87 |
/** Get the index of <code>rotation</code> among the connections. |
/** Get <code>rotation</code> from the middle connection. |
88 |
* E.g., when <code>rotation</code> is the first of the connections, |
* E.g., when there are 6 connections and the second one is selected, |
89 |
* then this returns 0; when the rotation is the third connection, |
* <code>rotation</code> is -1. |
90 |
* this returns 2. |
*/ |
91 |
*/ |
public int getRotation() { |
92 |
public int getRotationIndex() { |
return rotation; |
|
if(rotation == null) |
|
|
return 0; |
|
|
else if(getConnections(dir).contains(rotation)) |
|
|
return getConnections(dir).headSet(rotation).size(); |
|
|
else |
|
|
return 0; |
|
93 |
} |
} |
94 |
|
|
95 |
/** The posward or negward connections of <code>focus</code> to show, |
/** The posward or negward connections of <code>focus</code> to show, |
120 |
} |
} |
121 |
|
|
122 |
/** Rotate the view up or down. |
/** Rotate the view up or down. |
123 |
* This moves the rotation of the cursor one step up or down. XXX |
* This moves the rotation of the cursor up or down. |
124 |
*/ |
*/ |
125 |
public void rotate(int rdir) { |
public void rotate(int dir) { |
126 |
SortedSet |
SortedSet |
127 |
neg = getConnections(-1), |
neg = getConnections(-1), |
128 |
pos = getConnections(1); |
pos = getConnections(1); |
129 |
|
|
130 |
if(rotation == null) { |
int negn = neg.size(); |
131 |
if(pos.size() > 0) { |
int posn = pos.size(); |
|
rotation = (RDFNode)pos.iterator().next(); |
|
|
dir = 1; |
|
|
} else if(neg.size() > 0) { |
|
|
rotation = (RDFNode)neg.iterator().next(); |
|
|
dir = -1; |
|
|
} else |
|
|
return; |
|
|
} |
|
|
|
|
|
int i = getRotationIndex(); |
|
132 |
|
|
133 |
if(rdir < 0) i--; |
int n = (negn>posn) ? negn : posn; |
|
else i++; |
|
134 |
|
|
135 |
if(i < 0) return; |
int abs = (n-1)/2 + rotation + dir; |
|
if(i >= neg.size() && i >= pos.size()) return; |
|
136 |
|
|
137 |
List l; |
if(abs<0 || abs>=n) |
138 |
if(dir > 0) { |
return; |
|
if(pos.size() > i) |
|
|
l = new ArrayList(pos); |
|
|
else { |
|
|
l = new ArrayList(neg); |
|
|
dir = -1; |
|
|
} |
|
|
} else { |
|
|
if(neg.size() > i) |
|
|
l = new ArrayList(neg); |
|
|
else { |
|
|
l = new ArrayList(pos); |
|
|
dir = 1; |
|
|
} |
|
|
} |
|
139 |
|
|
140 |
rotation = (RDFNode)l.get(i); |
rotation += dir; |
141 |
} |
} |
142 |
|
|
143 |
/** Move left/right. XXX |
/** Get the index of the rotation in the list of |
144 |
|
* left/right connections. Can be out-of-bounds in that |
145 |
|
* it is smaller than zero or larger than the number |
146 |
|
* of items in the list: e.g. if you have 11 nodes |
147 |
|
* connected to the right and 3 nodes connected |
148 |
|
* to the left, when the last of the 11 nodes is selected, |
149 |
|
* getRotationIndex(-1) will return +7. XXX |
150 |
*/ |
*/ |
151 |
public void move(int mdir) { |
public int getRotationIndex(int dir) { |
152 |
Iterator iter = getConnections(mdir).iterator(); |
int n = getConnections(dir).size(); |
153 |
int n = getRotationIndex(); |
int abs = (n-1)/2 + rotation; |
154 |
|
return abs; |
155 |
|
} |
156 |
|
|
157 |
|
public RDFNode getRotationNode(int dir) { |
158 |
|
Iterator iter = getConnections(dir).iterator(); |
159 |
|
int n = getRotationIndex(dir); |
160 |
|
if(n < 0) |
161 |
|
// nothing there |
162 |
|
return null; |
163 |
for(int i=0; i<n; i++) if(iter.hasNext()) iter.next(); |
for(int i=0; i<n; i++) if(iter.hasNext()) iter.next(); |
164 |
if(!iter.hasNext()) |
if(!iter.hasNext()) |
165 |
// cannot move there |
// nothing there |
166 |
return; |
return null; |
167 |
rotation = focus; |
|
168 |
focus = (Resource)iter.next(); |
return (RDFNode)iter.next(); |
169 |
dir = -mdir; |
} |
170 |
|
|
171 |
|
/** Move left/right. XXX |
172 |
|
*/ |
173 |
|
public void move(int dir) { |
174 |
|
RDFNode node = getRotationNode(dir); |
175 |
|
if(node == null) return; |
176 |
|
set((Resource)node, -dir, focus); |
177 |
} |
} |
178 |
} |
} |