001: /* Copyright 2005 The JA-SIG Collaborative. All rights reserved.
002: * See license distributed with this file and
003: * available online at http://www.uportal.org/license.html
004: */
005:
006: package org.jasig.portal.layout.dlm;
007:
008: import org.jasig.portal.layout.node.IUserLayoutNodeDescription;
009:
010: /**
011: * A class that embodies the logic for determining if a node can be moved to
012: * the left or right of another node based on getMovedAllowed() and
013: * getPrecedence().
014: *
015: * @version $Revision: 36687 $ $Date: 2006-08-24 16:28:04 -0700 (Thu, 24 Aug 2006) $
016: * @since uPortal 2.5
017: */
018: public class MovementRules {
019: public static final String RCS_ID = "@(#) $Header$";
020:
021: /**
022: Returns true if hopper is allowed to hop in the rightward, higher-
023: sibling direction over the node being hopped; nbh. This is determined
024: from the following tables. See notes from canHopLeft for details. In
025: the tables below a zero equates to false and a one equates to true.
026: Since moveAllowed is an attribute on a node a value of false equates
027: to a string value of 'false'. The non-existence of a moveAllowed
028: attribute defaults to making that node moveable. In otherwords the
029: attribute is only included (asserted) when movement is being restricted.
030:
031: <pre>
032: Scenario | NBH | hopper |
033: | moveAllowed | moveAllowed |
034: ----------+-------------+-------------+
035: A | 0 | 0 |
036: B | 0 | 1 |
037: C | 1 | 0 |
038: D | 1 | 1 |
039: ----------+-------------+-------------+
040: </pre>
041:
042: In the table below Ph is the precedence of the hopper node. Pnbh is the
043: precedence of the node being hopped. The values in the table indicate
044: what values should be returned from this method. The scenarios A
045: through D are as defined above for the moveAllowed values.
046:
047: <pre>
048: Scenario --> | A | B | C | D |
049: -------------+---+---+---+---+
050: Pnbh = Ph | 0 | 0 | 0 | 1 |
051: Pnbh > Ph | 0 | 1 | 1 | 1 |
052: Pnbh < Ph | 0 | 1 | 0 | 1 |
053: -------------+---+---+---+---+
054: </pre>
055: */
056: public static boolean canHopRight(
057: IUserLayoutNodeDescription hopper,
058: IUserLayoutNodeDescription nbh) {
059: boolean nbhMoveAld = nbh.isMoveAllowed();
060: boolean hopperMoveAld = hopper.isMoveAllowed();
061:
062: if (nbhMoveAld == hopperMoveAld)
063: return nbhMoveAld;
064:
065: // from the above test we know that if we get here, moveAld's differ
066: double Pnbh = nbh.getPrecedence();
067: double Ph = hopper.getPrecedence();
068:
069: if (Pnbh > Ph)
070: return true;
071:
072: if (Pnbh < Ph && hopperMoveAld == true)
073: return true;
074:
075: return false;
076: }
077:
078: /**
079: Returns true if hopper is allowed to hop in the leftward, lower-
080: sibling direction over the node being hopped; nbh. This is determined
081: from the following tables. Since lower sibling order is tied to left or
082: top most viewing locations on the screen these positions are considered
083: to be superior in real-estate value. Hence to protect viewability as
084: much as possible within a precedence a fragment owner can movement
085: restrict a node, lets say a tab for example, to prevent users from
086: placing nodes with equal or lesser precedence to its left and
087: ultimately force that tab off of the right side of the screen.
088:
089: Sibling nodes are mapped left to right on the screen for lowest to
090: highest child node index in the parent node for tabs and columns and
091: from top to bottom on the screen for lowest to highest child node index
092: in the parent node for channels. In the tables below a
093: zero equates to false and a one equates to true.
094:
095: <pre>
096: Scenario | NBH | hopper |
097: | moveAllowed | moveAllowed |
098: ----------+-------------+-------------+
099: A | 0 | 0 |
100: B | 0 | 1 |
101: C | 1 | 0 |
102: D | 1 | 1 |
103: ----------+-------------+-------------+
104: </pre>
105:
106: In the table below Ph is the precedence of the hopper node. Pnbh is the
107: precedence of the node being hopped. The values in the table indicate
108: what values should be returned from this method. The scenarios are A
109: through D are as defined above for the moveAllowed values.
110:
111: These return values were
112: determined by setting up each scenario on paper with tabs as the nodes
113: and determining what expected and reasonable behavior should be. A
114: higher precedence value takes precedence over movement restrictions
115: imposed by a node from a fragment with lesser precedence.
116:
117: <pre>
118: Scenario --> | A | B | C | D |
119: -------------+---+---+---+---+
120: Pnbh = Ph | 0 | 0 | 0 | 1 |
121: Pnbh > Ph | 0 | 0 | 1 | 1 |
122: Pnbh < Ph | 0 | 1 | 1 | 1 |
123: -------------+---+---+---+---+
124: </pre>
125:
126: Patterns in these tables were used to simplify checks needed to return
127: the appropriate values. For example when the moveAllowed values are the
128: same the returned value matches the moveAllowed value.
129: */
130: public static boolean canHopLeft(IUserLayoutNodeDescription hopper,
131: IUserLayoutNodeDescription nbh) {
132: boolean nbhMoveAld = nbh.isMoveAllowed();
133: boolean hopperMoveAld = hopper.isMoveAllowed();
134:
135: if (nbhMoveAld == hopperMoveAld)
136: return nbhMoveAld;
137:
138: // from the above test we know that if we get here, moveAld's differ
139: double Pnbh = nbh.getPrecedence();
140: double Ph = hopper.getPrecedence();
141:
142: if (Pnbh < Ph)
143: return true;
144:
145: if (Pnbh > Ph && nbhMoveAld == true)
146: return true;
147:
148: return false;
149: }
150: }
|