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 
setComponentOrientation(ComponentOrientation orientation)50     void setComponentOrientation(ComponentOrientation orientation) {
51         horizontal = orientation.isHorizontal();
52         leftToRight = orientation.isLeftToRight();
53     }
54 
compare(Component a, Component b)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 }
161