1 /* 2 * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package javax.swing; 26 27 import java.util.Comparator; 28 import java.util.LinkedList; 29 import java.util.ListIterator; 30 import java.awt.Component; 31 import java.awt.ComponentOrientation; 32 import java.awt.Window; 33 34 35 /** 36 * Comparator which attempts to sort Components based on their size and 37 * position. Code adapted from original javax.swing.DefaultFocusManager 38 * implementation. 39 * 40 * @author David Mendenhall 41 */ 42 final class LayoutComparator implements Comparator<Component>, java.io.Serializable { 43 44 private static final int ROW_TOLERANCE = 10; 45 46 private boolean horizontal = true; 47 private boolean leftToRight = true; 48 49 void setComponentOrientation(ComponentOrientation orientation) { 50 horizontal = orientation.isHorizontal(); 51 leftToRight = orientation.isLeftToRight(); 52 } 53 54 public int compare(Component a, Component b) { 55 if (a == b) { 56 return 0; 57 } 58 59 // Row/Column algorithm only applies to siblings. If 'a' and 'b' 60 // aren't siblings, then we need to find their most inferior 61 // ancestors which share a parent. Compute the ancestory lists for 62 // each Component and then search from the Window down until the 63 // hierarchy branches. 64 if (a.getParent() != b.getParent()) { 65 LinkedList<Component> aAncestory = new LinkedList<Component>(); 66 67 for(; a != null; a = a.getParent()) { 68 aAncestory.add(a); 69 if (a instanceof Window) { 70 break; 71 } 72 } 73 if (a == null) { 74 // 'a' is not part of a Window hierarchy. Can't cope. 75 throw new ClassCastException(); 76 } 77 78 LinkedList<Component> bAncestory = new LinkedList<Component>(); 79 80 for(; b != null; b = b.getParent()) { 81 bAncestory.add(b); 82 if (b instanceof Window) { 83 break; 84 } 85 } 86 if (b == null) { 87 // 'b' is not part of a Window hierarchy. Can't cope. 88 throw new ClassCastException(); 89 } 90 91 for (ListIterator<Component> 92 aIter = aAncestory.listIterator(aAncestory.size()), 93 bIter = bAncestory.listIterator(bAncestory.size()); ;) { 94 if (aIter.hasPrevious()) { 95 a = aIter.previous(); 96 } else { 97 // a is an ancestor of b 98 return -1; 99 } 100 101 if (bIter.hasPrevious()) { 102 b = bIter.previous(); 103 } else { 104 // b is an ancestor of a 105 return 1; 106 } 107 108 if (a != b) { 109 break; 110 } 111 } 112 } 113 114 int ax = a.getX(), ay = a.getY(), bx = b.getX(), by = b.getY(); 115 116 int zOrder = a.getParent().getComponentZOrder(a) - b.getParent().getComponentZOrder(b); 117 if (horizontal) { 118 if (leftToRight) { 119 120 // LT - Western Europe (optional for Japanese, Chinese, Korean) 121 122 if (Math.abs(ay - by) < ROW_TOLERANCE) { 123 return (ax < bx) ? -1 : ((ax > bx) ? 1 : zOrder); 124 } else { 125 return (ay < by) ? -1 : 1; 126 } 127 } else { // !leftToRight 128 129 // RT - Middle East (Arabic, Hebrew) 130 131 if (Math.abs(ay - by) < ROW_TOLERANCE) { 132 return (ax > bx) ? -1 : ((ax < bx) ? 1 : zOrder); 133 } else { 134 return (ay < by) ? -1 : 1; 135 } 136 } 137 } else { // !horizontal 138 if (leftToRight) { 139 140 // TL - Mongolian 141 142 if (Math.abs(ax - bx) < ROW_TOLERANCE) { 143 return (ay < by) ? -1 : ((ay > by) ? 1 : zOrder); 144 } else { 145 return (ax < bx) ? -1 : 1; 146 } 147 } else { // !leftToRight 148 149 // TR - Japanese, Chinese, Korean 150 151 if (Math.abs(ax - bx) < ROW_TOLERANCE) { 152 return (ay < by) ? -1 : ((ay > by) ? 1 : zOrder); 153 } else { 154 return (ax > bx) ? -1 : 1; 155 } 156 } 157 } 158 } 159 }