1 /* 2 * Copyright (c) 2000, 2014, 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 @SuppressWarnings("serial") // JDK-implementation class 43 final class LayoutComparator implements Comparator<Component>, java.io.Serializable { 44 45 private static final int ROW_TOLERANCE = 10; 46 47 private boolean horizontal = true; 48 private boolean leftToRight = true; 49 50 void setComponentOrientation(ComponentOrientation orientation) { 51 horizontal = orientation.isHorizontal(); 52 leftToRight = orientation.isLeftToRight(); 53 } 54 55 public int compare(Component a, Component b) { 56 if (a == b) { 57 return 0; 58 } 59 60 // Row/Column algorithm only applies to siblings. If 'a' and 'b' 61 // aren't siblings, then we need to find their most inferior 62 // ancestors which share a parent. Compute the ancestory lists for 63 // each Component and then search from the Window down until the 64 // hierarchy branches. 65 if (a.getParent() != b.getParent()) { 66 LinkedList<Component> aAncestory = new LinkedList<Component>(); 67 68 for(; a != null; a = a.getParent()) { 69 aAncestory.add(a); 70 if (a instanceof Window) { 71 break; 72 } 73 } 74 if (a == null) { 75 // 'a' is not part of a Window hierarchy. Can't cope. 76 throw new ClassCastException(); 77 } 78 79 LinkedList<Component> bAncestory = new LinkedList<Component>(); 80 81 for(; b != null; b = b.getParent()) { 82 bAncestory.add(b); 83 if (b instanceof Window) { 84 break; 85 } 86 } 87 if (b == null) { 88 // 'b' is not part of a Window hierarchy. Can't cope. 89 throw new ClassCastException(); 90 } 91 92 for (ListIterator<Component> 93 aIter = aAncestory.listIterator(aAncestory.size()), 94 bIter = bAncestory.listIterator(bAncestory.size()); ;) { 95 if (aIter.hasPrevious()) { 96 a = aIter.previous(); 97 } else { 98 // a is an ancestor of b 99 return -1; 100 } 101 102 if (bIter.hasPrevious()) { 103 b = bIter.previous(); 104 } else { 105 // b is an ancestor of a 106 return 1; 107 } 108 109 if (a != b) { 110 break; 111 } 112 } 113 } 114 115 int ax = a.getX(), ay = a.getY(), bx = b.getX(), by = b.getY(); 116 117 int zOrder = a.getParent().getComponentZOrder(a) - b.getParent().getComponentZOrder(b); 118 if (horizontal) { 119 if (leftToRight) { 120 121 // LT - Western Europe (optional for Japanese, Chinese, Korean) 122 123 if (Math.abs(ay - by) < ROW_TOLERANCE) { 124 return (ax < bx) ? -1 : ((ax > bx) ? 1 : zOrder); 125 } else { 126 return (ay < by) ? -1 : 1; 127 } 128 } else { // !leftToRight 129 130 // RT - Middle East (Arabic, Hebrew) 131 132 if (Math.abs(ay - by) < ROW_TOLERANCE) { 133 return (ax > bx) ? -1 : ((ax < bx) ? 1 : zOrder); 134 } else { 135 return (ay < by) ? -1 : 1; 136 } 137 } 138 } else { // !horizontal 139 if (leftToRight) { 140 141 // TL - Mongolian 142 143 if (Math.abs(ax - bx) < ROW_TOLERANCE) { 144 return (ay < by) ? -1 : ((ay > by) ? 1 : zOrder); 145 } else { 146 return (ax < bx) ? -1 : 1; 147 } 148 } else { // !leftToRight 149 150 // TR - Japanese, Chinese, Korean 151 152 if (Math.abs(ax - bx) < ROW_TOLERANCE) { 153 return (ay < by) ? -1 : ((ay > by) ? 1 : zOrder); 154 } else { 155 return (ax > bx) ? -1 : 1; 156 } 157 } 158 } 159 } 160 }