aboutsummaryrefslogtreecommitdiff
path: root/libjava/java/sql/DatabaseMetaData.java
blob: c2f389b88310cd8859e8c681abd866d2b334e530 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
/* DatabaseMetaData.java -- Information about the database itself.
   Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
 
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.sql;

/**
  * This interface provides a mechanism for obtaining information about
  * the database itself, as opposed to data in it.
  *
  * @author Aaron M. Renn (arenn@urbanophile.com)
  */
public interface DatabaseMetaData
{

/**
  * The best row may or may not be a pseudo-column.
  */
public static final int bestRowUnknown = 0;

/**
  * The best row identifier is not a pseudo-column.
  */
public static final int bestRowNotPseudo = 1;

/**
  * The best row identifier is a pseudo-column.
  */
public static final int bestRowPseudo = 2;

/**
  * The best row's scope is only guaranteed to be valid so long as the
  * row is actually being used.
  */
public static final int bestRowTemporary = 0;

/**
  * The best row identifier is valid to the end of the transaction.
  */
public static final int bestRowTransaction = 1;

/**
  * The best row identifier is valid to the end of the session.
  */
public static final int bestRowSession = 2;

/**
  * It is unknown whether or not the procedure returns a result.
  */
public static final int procedureResultUnknown = 0;

/**
  * The procedure does not return a result.
  */
public static final int procedureNoResult = 1;

/**
  * The procedure returns a result.
  */
public static final int procedureReturnsResult = 2;

/**
  * The column type is unknown.
  */
public static final int procedureColumnUnknown = 0;

/**
  * The column type is input.
  */
public static final int procedureColumnIn = 1;

/**
  * The column type is input/output.
  */
public static final int procedureColumnInOut = 2;

/**
  * The column type is output
  */
public static final int procedureColumnOut = 4;

/**
  * The column is used for return values.
  */
public static final int procedureColumnReturn = 5;

/**
  * The column is used for storing results
  */
public static final int procedureColumnResult = 3;

/**
  * NULL values are not allowed.
  */
public static final int procedureNoNulls = 0;

/**
  * NULL values are allowed.
  */
public static final int procedureNullable = 1;

/**
  * It is unknown whether or not NULL values are allowed.
  */
public static final int procedureNullableUnknown = 2;

/**
  * The column does not allow NULL
  */
public static final int columnNoNulls = 0;

/**
  * The column does allow NULL
  */
public static final int columnNullable = 1;

/**
  * It is unknown whether or not the column allows NULL
  */
public static final int columnNullableUnknown = 2;

/**
  * It is unknown whether or not the version column is a pseudo-column.
  */
public static final int versionColumnUnknown = 0;

/**
  * The version column is not a pseudo-column
  */
public static final int versionColumnNotPseudo = 1;

/**
  * The version column is a pseudo-column
  */
public static final int versionColumnPseudo = 2;

/**
  * Foreign key changes are cascaded in updates or deletes.
  */
public static final int importedKeyCascade = 0;

/**
  * Column may not be updated or deleted in use as a foreign key.
  */
public static final int importedKeyRestrict = 1;

/**
  * When primary key is updated or deleted, the foreign key is set to NULL.
  */
public static final int importedKeySetNull = 2;

/**
  * If the primary key is a foreign key, it cannot be udpated or deleted.
  */
public static final int importedKeyNoAction = 3;

/**
  * If the primary key is updated or deleted, the foreign key is set to
  * a default value.
  */
public static final int importedKeySetDefault = 4;

/**
  * Wish I knew what this meant.
  */
public static final int importedKeyInitiallyDeferred = 5;

/**
  * Wish I knew what this meant.
  */
public static final int importedKeyInitiallyImmediate = 6;

/**
  * Wish I knew what this meant.
  */
public static final int importedKeyNotDeferrable = 7;

/**
  * A NULL value is not allowed for this data type.
  */
public static final int typeNoNulls = 0;

/**
  * A NULL value is allowed for this data type.
  */
public static final int typeNullable = 1;

/**
  * It is unknown whether or not NULL values are allowed for this data type.
  */
public static final int typeNullableUnknown = 2;

/**
  * Where clauses are not supported for this type.
  */
public static final int typePredNone = 0;

/**
  * Only "WHERE..LIKE" style WHERE clauses are allowed on this data type.
  */
public static final int typePredChar = 1;

/**
  * All WHERE clauses except "WHERE..LIKE" style are allowed on this data type.
  */
public static final int typePredBasic = 2;

/**
  * Any type of WHERE clause is allowed for this data type.
  */
public static final int typeSearchable = 3;

/**
  * This column contains table statistics.
  */
public static final short tableIndexStatistic = 0;

/**
  * This table index is clustered.
  */
public static final short tableIndexClustered = 1;

/**
  * This table index is hashed.
  */
public static final short tableIndexHashed = 2;

/**
  * This table index is of another type.
  */
public static final short tableIndexOther = 3;

/*************************************************************************/

/**
  * This method tests whether or not all the procedures returned by
  * the <code>getProcedures</code> method can be called by this user.
  *
  * @return <code>true</code> if all the procedures can be called,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
allProceduresAreCallable() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not all the table returned by the
  * <code>getTables</code> method can be selected by this user.
  *
  * @return <code>true</code> if all the procedures can be called,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
allTablesAreSelectable() throws SQLException;

/*************************************************************************/

/**
  * This method returns the URL for this database.
  *
  * @return The URL string for this database, or <code>null</code> if it
  * is not known.
  *
  * @exception SQLException If an error occurs.
  */
public abstract String
getURL() throws SQLException;

/*************************************************************************/

/**
  * This method returns the database username for this connection.
  *
  * @return The database username.
  *
  * @exception SQLException If an error occurs.
  */
public abstract String
getUserName() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the database is in read only mode.
  *
  * @return <code>true</code> if the database is in read only mode,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
isReadOnly() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not NULL's sort as high values.
  *
  * @return <code>true</code> if NULL's sort as high values, <code>false</code>
  * otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
nullsAreSortedHigh() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not NULL's sort as low values.
  *
  * @return <code>true</code> if NULL's sort as low values, <code>false</code>
  * otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
nullsAreSortedLow() throws SQLException;

/*************************************************************************/

/**
  * This method test whether or not NULL's are sorted to the beginning
  * of the list regardless of ascending or descending sort order.
  *
  * @return <code>true</code> if NULL's always sort to the beginning,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
nullsAreSortedAtStart() throws SQLException;

/*************************************************************************/

/**
  * This method test whether or not NULL's are sorted to the end
  * of the list regardless of ascending or descending sort order.
  *
  * @return <code>true</code> if NULL's always sort to the end,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
nullsAreSortedAtEnd() throws SQLException;

/*************************************************************************/

/**
  * This method returns the name of the database product.
  *
  * @return The database product.
  *
  * @exception SQLException If an error occurs.
  */
public abstract String
getDatabaseProductName() throws SQLException;

/*************************************************************************/

/**
  * This method returns the version of the database product.
  *
  * @return The version of the database product.
  *
  * @exception SQLException If an error occurs.
  */
public abstract String
getDatabaseProductVersion() throws SQLException;

/*************************************************************************/

/**
  * This method returns the name of the JDBC driver.
  *
  * @return The name of the JDBC driver.
  *
  * @exception SQLException If an error occurs.
  */
public abstract String
getDriverName() throws SQLException;

/*************************************************************************/

/**
  * This method returns the version of the JDBC driver.
  *
  * @return The version of the JDBC driver.
  *
  * @exception SQLException If an error occurs.
  */
public abstract String
getDriverVersion() throws SQLException;

/*************************************************************************/

/**
  * This method returns the major version number of the JDBC driver.
  *
  * @return The major version number of the JDBC driver.
  */
public abstract int
getDriverMajorVersion();

/*************************************************************************/

/**
  * This method returns the minor version number of the JDBC driver.
  *
  * @return The minor version number of the JDBC driver.
  */
public abstract int
getDriverMinorVersion();

/*************************************************************************/

/**
  * This method tests whether or not the database uses local files to
  * store tables.
  *
  * @return <code>true</code> if the database uses local files, 
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
usesLocalFiles() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the database uses a separate file for
  * each table.
  *
  * @return <code>true</code> if the database uses a separate file for each
  * table </code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
usesLocalFilePerTable() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the database supports identifiers
  * with mixed case.
  *
  * @return <code>true</code> if the database supports mixed case identifiers,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsMixedCaseIdentifiers() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the database treats mixed case
  * identifiers as all upper case.
  *
  * @exception <code>true</code> if the database treats all identifiers as
  * upper case, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
storesUpperCaseIdentifiers() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the database treats mixed case
  * identifiers as all lower case.
  *
  * @exception <code>true</code> if the database treats all identifiers as
  * lower case, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
storesLowerCaseIdentifiers() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the database stores mixed case 
  * identifers even if it treats them as case insensitive.
  *
  * @return <code>true</code> if the database stores mixed case identifiers,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
storesMixedCaseIdentifiers() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the database supports quoted identifiers
  * with mixed case.
  *
  * @return <code>true</code> if the database supports mixed case quoted
  * identifiers, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsMixedCaseQuotedIdentifiers() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the database treats mixed case
  * quoted identifiers as all upper case.
  *
  * @exception <code>true</code> if the database treats all quoted identifiers 
  * as upper case, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
storesUpperCaseQuotedIdentifiers() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the database treats mixed case
  * quoted identifiers as all lower case.
  *
  * @exception <code>true</code> if the database treats all quoted identifiers 
  * as lower case, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
storesLowerCaseQuotedIdentifiers() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the database stores mixed case 
  * quoted identifers even if it treats them as case insensitive.
  *
  * @return <code>true</code> if the database stores mixed case quoted 
  * identifiers, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
storesMixedCaseQuotedIdentifiers() throws SQLException;

/*************************************************************************/

/**
  * This metohd returns the quote string for SQL identifiers.
  *
  * @return The quote string for SQL identifers, or a space if quoting
  * is not supported.
  *
  * @exception SQLException If an error occurs.
  */
public abstract String
getIdentifierQuoteString() throws SQLException;

/*************************************************************************/

/**
  * This method returns a comma separated list of all the SQL keywords in
  * the database that are not in SQL92.
  *
  * @return The list of SQL keywords not in SQL92.
  *
  * @exception SQLException If an error occurs.
  */
public abstract String
getSQLKeywords() throws SQLException;

/*************************************************************************/

/**
  * This method returns a comma separated list of math functions.
  *
  * @return The list of math functions.
  *
  * @exception SQLException If an error occurs.
  */
public abstract String
getNumericFunctions() throws SQLException;

/*************************************************************************/

/**
  * This method returns a comma separated list of string functions.
  *
  * @return The list of string functions.
  * 
  * @exception SQLException If an error occurs.
  */
public abstract String
getStringFunctions() throws SQLException;

/*************************************************************************/

/**
  * This method returns a comma separated list of of system functions.
  *
  * @return A comma separated list of system functions.
  *
  * @exception SQLException If an error occurs.
  */
public abstract String
getSystemFunctions() throws SQLException;

/*************************************************************************/

/**
  * This method returns comma separated list of time/date functions.
  * 
  * @return The list of time/date functions.
  *
  * @exception SQLException If an error occurs.
  */
public abstract String
getTimeDateFunctions() throws SQLException;

/*************************************************************************/

/**
  * This method returns the string used to escape wildcards in search strings.
  *
  * @return The string used to escape wildcards in search strings.
  *
  * @exception SQLException If an error occurs.
  */
public abstract String
getSearchStringEscape() throws SQLException;

/*************************************************************************/

/**
  * This methods returns non-standard characters that can appear in 
  * unquoted identifiers.
  *
  * @return Non-standard characters that can appear in unquoted identifiers.
  *
  * @exception SQLException If an error occurs.
  */
public abstract String
getExtraNameCharacters() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the database supports
  * "ALTER TABLE ADD COLUMN"
  *
  * @return <code>true</code> if column add supported, <code>false</code>
  * otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsAlterTableWithAddColumn() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the database supports
  * "ALTER TABLE DROP COLUMN"
  *
  * @return <code>true</code> if column drop supported, <code>false</code>
  * otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsAlterTableWithDropColumn() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not column aliasing is supported.
  *
  * @return <code>true</code> if column aliasing is supported,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsColumnAliasing() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether the concatenation of a NULL and non-NULL
  * value results in a NULL.  This will always be true in fully JDBC compliant
  * drivers.
  *
  * @return <code>true</code> if concatenating NULL and a non-NULL value
  * returns a NULL, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
nullPlusNonNullIsNull() throws SQLException;

/*************************************************************************/

/**
  * Tests whether or not CONVERT is supported.
  *
  * @return <code>true</code> if CONVERT is supported, <code>false</code>
  * otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsConvert() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not CONVERT can be performed between the
  * specified types.  The types are contants from <code>Types</code>.
  *
  * @param fromType The SQL type to convert from.
  * @param toType The SQL type to convert to.
  * 
  * @return <code>true</code> if the conversion can be performed,
  * <code>false</code> otherwise.
  *
  * @see Types
  */
public abstract boolean
supportsConvert(int fromType, int toType) throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not table correlation names are 
  * supported.  This will be always be <code>true</code> in a fully JDBC
  * compliant driver.
  *
  * @return <code>true</code> if table correlation names are supported,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsTableCorrelationNames() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether correlation names must be different from the
  * name of the table.
  *
  * @return <code>true</code> if the correlation name must be different from
  * the table name, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsDifferentTableCorrelationNames() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not expressions are allowed in an
  * ORDER BY lists.
  *
  * @return <code>true</code> if expressions are allowed in ORDER BY
  * lists, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsExpressionsInOrderBy() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or ORDER BY on a non-selected column is
  * allowed.
  *
  * @return <code>true</code> if a non-selected column can be used in an
  * ORDER BY, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsOrderByUnrelated() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not GROUP BY is supported.
  *
  * @return <code>true</code> if GROUP BY is supported, <code>false</code>
  * otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsGroupBy() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether GROUP BY on a non-selected column is
  * allowed.
  *
  * @return <code>true</code> if a non-selected column can be used in a
  * GROUP BY, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsGroupByUnrelated() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not a GROUP BY can add columns not in the
  * select if it includes all the columns in the select.
  *
  * @return <code>true</code> if GROUP BY an add columns provided it includes
  * all columns in the select, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsGroupByBeyondSelect() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the escape character is supported in
  * LIKE expressions.  A fully JDBC compliant driver will always return
  * <code>true</code>.
  *
  * @return <code>true</code> if escapes are supported in LIKE expressions,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean supportsLikeEscapeClause() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether multiple result sets for a single statement are
  * supported.
  *
  * @return <code>true</code> if multiple result sets are supported for a 
  * single statement, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsMultipleResultSets() throws SQLException;

/*************************************************************************/

/**
  * This method test whether or not multiple transactions may be open
  * at once, as long as they are on different connections.
  *
  * @return <code>true</code> if multiple transactions on different
  * connections are supported, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsMultipleTransactions() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not columns can be defined as NOT NULL.  A
  * fully JDBC compliant driver always returns <code>true</code>.
  *
  * @return <code>true</code> if NOT NULL columns are supported,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsNonNullableColumns() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the minimum grammer for ODBC is supported.
  * A fully JDBC compliant driver will always return <code>true</code>.
  *
  * @return <code>true</code> if the ODBC minimum grammar is supported,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsMinimumSQLGrammar() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the core grammer for ODBC is supported.
  *
  * @return <code>true</code> if the ODBC core grammar is supported,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsCoreSQLGrammar() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the extended grammer for ODBC is supported.
  *
  * @return <code>true</code> if the ODBC extended grammar is supported,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsExtendedSQLGrammar() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the ANSI92 entry level SQL
  * grammar is supported.  A fully JDBC compliant drivers must return
  * <code>true</code>.
  *
  * @return <code>true</code> if the ANSI92 entry level SQL grammar is
  * supported, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsANSI92EntryLevelSQL() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the ANSI92 intermediate SQL
  * grammar is supported.  
  *
  * @return <code>true</code> if the ANSI92 intermediate SQL grammar is
  * supported, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsANSI92IntermediateSQL() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the ANSI92 full SQL
  * grammar is supported.  
  *
  * @return <code>true</code> if the ANSI92 full SQL grammar is
  * supported, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsANSI92FullSQL() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the SQL integrity enhancement
  * facility is supported.
  *
  * @return <code>true</code> if the integrity enhancement facility is
  * supported, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsIntegrityEnhancementFacility() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the database supports outer joins.
  *
  * @return <code>true</code> if outer joins are supported, <code>false</code>
  * otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsOuterJoins() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the database supports full outer joins.
  *
  * @return <code>true</code> if full outer joins are supported, 
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsFullOuterJoins() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the database supports limited outer joins.
  *
  * @return <code>true</code> if limited outer joins are supported, 
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsLimitedOuterJoins() throws SQLException;

/*************************************************************************/

/**
  * This method returns the vendor's term for "schema".
  *
  * @return The vendor's term for schema.
  *
  * @exception SQLException if an error occurs.
  */
public abstract String
getSchemaTerm() throws SQLException;

/*************************************************************************/

/**
  * This method returns the vendor's term for "procedure".
  *
  * @return The vendor's term for procedure.
  *
  * @exception SQLException if an error occurs.
  */
public abstract String
getProcedureTerm() throws SQLException;

/*************************************************************************/

/**
  * This method returns the vendor's term for "catalog".
  *
  * @return The vendor's term for catalog.
  *
  * @exception SQLException if an error occurs.
  */
public abstract String
getCatalogTerm() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether a catalog name appears at the beginning of
  * a fully qualified table name.
  *
  * @return <code>true</code> if the catalog name appears at the beginning,
  * <code>false</code> if it appears at the end.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
isCatalogAtStart() throws SQLException;

/*************************************************************************/

/**
  * This method returns the separator between the catalog name and the
  * table name.
  *
  * @return The separator between the catalog name and the table name.
  *
  * @exception SQLException If an error occurs.
  */
public abstract String
getCatalogSeparator() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether a catalog name can appear in a data
  * manipulation statement.
  *
  * @return <code>true</code> if a catalog name can appear in a data
  * manipulation statement, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsSchemasInDataManipulation() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether a catalog name can appear in a procedure
  * call
  *
  * @return <code>true</code> if a catalog name can appear in a procedure
  * call, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsSchemasInProcedureCalls() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether a catalog name can appear in a table definition.
  *
  * @return <code>true</code> if a catalog name can appear in a table
  * definition, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsSchemasInTableDefinitions() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether a catalog name can appear in an index definition.
  *
  * @return <code>true</code> if a catalog name can appear in an index
  * definition, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsSchemasInIndexDefinitions() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether a catalog name can appear in privilege definitions.
  *
  * @return <code>true</code> if a catalog name can appear in privilege
  * definition, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsSchemasInPrivilegeDefinitions() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether a catalog name can appear in a data
  * manipulation statement.
  *
  * @return <code>true</code> if a catalog name can appear in a data
  * manipulation statement, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsCatalogsInDataManipulation() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether a catalog name can appear in a procedure
  * call
  *
  * @return <code>true</code> if a catalog name can appear in a procedure
  * call, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsCatalogsInProcedureCalls() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether a catalog name can appear in a table definition.
  *
  * @return <code>true</code> if a catalog name can appear in a table
  * definition, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsCatalogsInTableDefinitions() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether a catalog name can appear in an index definition.
  *
  * @return <code>true</code> if a catalog name can appear in an index
  * definition, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsCatalogsInIndexDefinitions() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether a catalog name can appear in privilege definitions.
  *
  * @return <code>true</code> if a catalog name can appear in privilege
  * definition, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsCatalogsInPrivilegeDefinitions() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not that database supports positioned
  * deletes.
  *
  * @return <code>true</code> if positioned deletes are supported,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsPositionedDelete() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not that database supports positioned
  * updates.
  *
  * @return <code>true</code> if positioned updates are supported,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsPositionedUpdate() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not SELECT FOR UPDATE is supported by the
  * database.
  *
  * @return <code>true</code> if SELECT FOR UPDATE is supported 
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsSelectForUpdate() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not stored procedures are supported on
  * this database.
  *
  * @return <code>true</code> if stored procedures are supported,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsStoredProcedures() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not subqueries are allowed in comparisons.
  * A fully JDBC compliant driver will always return <code>true</code>.
  *
  * @return <code>true</code> if subqueries are allowed in comparisons,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsSubqueriesInComparisons() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not subqueries are allowed in exists
  * expressions.  A fully JDBC compliant driver will always return
  * <code>true</code>.
  *
  * @return <code>true</code> if subqueries are allowed in exists 
  * expressions, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsSubqueriesInExists() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether subqueries are allowed in IN statements.
  * A fully JDBC compliant driver will always return <code>true</code>.
  *
  * @return <code>true</code> if the driver supports subqueries in IN
  * statements, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsSubqueriesInIns() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not subqueries are allowed in quantified
  * expressions.  A fully JDBC compliant driver will always return
  * <code>true</code>.
  *
  * @return <code>true</code> if subqueries are allowed in quantified 
  * expressions, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsSubqueriesInQuantifieds() throws SQLException;

/*************************************************************************/

/**
  * This method test whether or not correlated subqueries are allowed. A
  * fully JDBC compliant driver will always return <code>true</code>.
  *
  * @return <code>true</code> if correlated subqueries are allowed,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsCorrelatedSubqueries() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the UNION statement is supported.
  *
  * @return <code>true</code> if UNION is supported, <code>false</code>
  * otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsUnion() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the UNION ALL statement is supported.
  *
  * @return <code>true</code> if UNION ALL is supported, <code>false</code>
  * otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsUnionAll() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the database supports cursors
  * remaining open across commits.
  *
  * @return <code>true</code> if cursors can remain open across commits,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsOpenCursorsAcrossCommit() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the database supports cursors
  * remaining open across rollbacks.
  *
  * @return <code>true</code> if cursors can remain open across rollbacks,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsOpenCursorsAcrossRollback() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the database supports statements
  * remaining open across commits.
  *
  * @return <code>true</code> if statements can remain open across commits,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsOpenStatementsAcrossCommit() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the database supports statements
  * remaining open across rollbacks.
  *
  * @return <code>true</code> if statements can remain open across rollbacks,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsOpenStatementsAcrossRollback() throws SQLException;

/*************************************************************************/

/**
  * This method returns the number of hex characters allowed in an inline
  * binary literal.
  *
  * @return The number of hex characters allowed in a binary literal, 0 meaning
  * either an unknown or unlimited number.
  *
  * @exception SQLException If an error occurs.
  */
public abstract int
getMaxBinaryLiteralLength() throws SQLException;

/*************************************************************************/

/**
  * This method returns the maximum length of a character literal.
  * 
  * @return The maximum length of a character literal.
  *
  * @exception SQLException If an error occurs.
  */
public abstract int
getMaxCharLiteralLength() throws SQLException;

/*************************************************************************/

/**
  * This method returns the maximum length of a column name.
  *
  * @return The maximum length of a column name.
  *
  * @exception SQLException If an error occurs.
  */
public abstract int
getMaxColumnNameLength() throws SQLException;

/*************************************************************************/

/**
  * This method returns the maximum number of columns in a GROUP BY statement.
  *
  * @return The maximum number of columns in a GROUP BY statement.
  *
  * @exception SQLException If an error occurs.
  */
public abstract int
getMaxColumnsInGroupBy() throws SQLException;

/*************************************************************************/

/**
  * This method returns the maximum number of columns in an index.
  *
  * @return The maximum number of columns in an index.
  *
  * @exception SQLException If an error occurs.
  */
public abstract int
getMaxColumnsInIndex() throws SQLException;

/*************************************************************************/

/**
  * This method returns the maximum number of columns in an ORDER BY statement.
  *
  * @return The maximum number of columns in an ORDER BY statement.
  *
  * @exception SQLException If an error occurs.
  */
public abstract int
getMaxColumnsInOrderBy() throws SQLException;

/*************************************************************************/

/**
  * This method returns the maximum number of columns in a SELECT statement.
  *
  * @return The maximum number of columns in a SELECT statement.
  *
  * @exception SQLException If an error occurs.
  */
public abstract int
getMaxColumnsInSelect() throws SQLException;

/*************************************************************************/

/**
  * This method returns the maximum number of columns in a table.
  *
  * @return The maximum number of columns in a table.
  *
  * @exception SQLException If an error occurs.
  */
public abstract int
getMaxColumnsInTable() throws SQLException;

/*************************************************************************/

/**
  * This method returns the maximum number of connections this client
  * can have to the database.
  *
  * @return The maximum number of database connections.
  *
  * @SQLException If an error occurs.
  */
public abstract int
getMaxConnections() throws SQLException;

/*************************************************************************/

/**
  * This method returns the maximum length of a cursor name.
  *
  * @return The maximum length of a cursor name.
  *
  * @exception SQLException If an error occurs.
  */
public abstract int
getMaxCursorNameLength() throws SQLException;

/*************************************************************************/

/**
  * This method returns the maximum length of an index.
  *
  * @return The maximum length of an index.
  *
  * @exception SQLException If an error occurs.
  */
public abstract int
getMaxIndexLength() throws SQLException;

/*************************************************************************/

/**
  * This method returns the maximum length of a schema name.
  *
  * @return The maximum length of a schema name.
  *
  * @exception SQLException If an error occurs.
  */
public abstract int
getMaxSchemaNameLength() throws SQLException;

/*************************************************************************/

/**
  * This method returns the maximum length of a procedure name.
  *
  * @return The maximum length of a procedure name.
  *
  * @exception SQLException If an error occurs.
  */
public abstract int
getMaxProcedureNameLength() throws SQLException;

/*************************************************************************/

/**
  * This method returns the maximum length of a catalog name.
  *
  * @return The maximum length of a catalog name.
  *
  * @exception SQLException If an error occurs.
  */
public abstract int
getMaxCatalogNameLength() throws SQLException;

/*************************************************************************/

/**
  * This method returns the maximum size of a row in bytes.
  *
  * @return The maximum size of a row.
  *
  * @exception SQLException If an error occurs.
  */
public abstract int
getMaxRowSize() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the maximum row size includes BLOB's
  *
  * @return <code>true</code> if the maximum row size includes BLOB's,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
doesMaxRowSizeIncludeBlobs() throws SQLException;

/*************************************************************************/

/**
  * This method includes the maximum length of a SQL statement.
  *
  * @return The maximum length of a SQL statement.
  *
  * @exception SQLException If an error occurs.
  */
public abstract int
getMaxStatementLength() throws SQLException;

/*************************************************************************/

/**
  * This method returns the maximum number of statements that can be
  * active at any time.
  *
  * @return The maximum number of statements that can be active at any time.
  * 
  * @exception SQLException If an error occurs.
  */
public abstract int
getMaxStatements() throws SQLException;

/*************************************************************************/

/**
  * This method returns the maximum length of a table name.
  *
  * @return The maximum length of a table name.
  *
  * @exception SQLException If an error occurs.
  */
public abstract int
getMaxTableNameLength() throws SQLException;

/*************************************************************************/

/**
  * This method returns the maximum number of tables that may be referenced
  * in a SELECT statement.
  *
  * @return The maximum number of tables allowed in a SELECT statement.
  *
  * @exception SQLException If an error occurs.
  */
public abstract int
getMaxTablesInSelect() throws SQLException;

/*************************************************************************/

/**
  * This method returns the maximum length of a user name.
  *
  * @return The maximum length of a user name.
  *
  * @exception SQLException If an error occurs.
  */
public abstract int
getMaxUserNameLength() throws SQLException;

/*************************************************************************/

/**
  * This method returns the default transaction isolation level of the
  * database.
  *
  * @return The default transaction isolation level of the database.
  *
  * @exception SQLException If an error occurs.
  *
  * @see Connection
  */
public abstract int
getDefaultTransactionIsolation() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the database supports transactions.
  *
  * @return <code>true</code> if the database supports transactions,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsTransactions() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the database supports the specified
  * transaction isolation level.
  *
  * @param level The transaction isolation level.
  *
  * @return <code>true</code> if the specified transaction isolation level
  * is supported, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsTransactionIsolationLevel(int level) throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not DDL and DML statements allowed within 
  * the same transaction.
  *
  * @return <code>true</code> if DDL and DML statements are allowed in the
  * same transaction, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsDataDefinitionAndDataManipulationTransactions() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not only DML statement are allowed
  * inside a transaction.
  *
  * @return <code>true</code> if only DML statements are allowed in
  * transactions, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsDataManipulationTransactionsOnly() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not a DDL statement will cause the
  * current transaction to be automatically committed.
  *
  * @return <code>true</code> if DDL causes an immediate transaction commit,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
dataDefinitionCausesTransactionCommit() throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not DDL statements are ignored in
  * transactions.
  *
  * @return <code>true</code> if DDL statements are ignored in transactions,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
dataDefinitionIgnoredInTransactions() throws SQLException;

/*************************************************************************/

/**
  * This method returns a list of all the stored procedures matching the
  * specified pattern in the given schema and catalog.  This is returned
  * a <code>ResultSet</code> with the following columns:
  * <p>
  * <ol>
  * <li>PROCEDURE_CAT - The catalog the procedure is in, which may be 
  * <code>null</code>.
  * <li>PROCEDURE_SCHEM - The schema the procedures is in, which may be
  * <code>null</code>.
  * <li>PROCEDURE_NAME - The name of the procedure.
  * <li>Unused
  * <li>Unused
  * <li>Unused
  * <li>REMARKS - A description of the procedure
  * <li>PROCEDURE_TYPE - Indicates the return type of the procedure, which 
  * is one of the contstants defined in this class 
  * (<code>procedureResultUnknown</code>, <code>procedureNoResult</code>, or
  * <code>procedureReturnsResult</code>).
  * </ol>
  *
  * @param catalog The name of the catalog to return stored procedured from,
  * or "" to return procedures from all catalogs.
  * @param schemaPattern A schema pattern for the schemas to return stored
  * procedures from, or "" to return procedures from all schemas.
  * @param namePattern The pattern of procedures names to return.
  *
  * @returns A <code>ResultSet</code> with all the requested procedures.
  *
  * @exception SQLException If an error occurs.
  */
public abstract ResultSet
getProcedures(String catalog, String schemaPattern, String namePattern)
              throws SQLException;

/*************************************************************************/

/**
  * This method returns a list of the parameter and result columns for
  * the requested stored procedures.  This is returned in the form of a
  * <code>ResultSet</code> with the following columns:
  * <p>
  * <ol>
  * <li>PROCEDURE_CAT - The catalog the procedure is in, which may be 
  * <code>null</code>.
  * <li>PROCEDURE_SCHEM - The schema the procedures is in, which may be
  * <code>null</code>.
  * <li>PROCEDURE_NAME - The name of the procedure.
  * <li>COLUMN_NAME - The name of the column
  * <li>COLUMN_TYPE - The type of the column, which will be one of the
  * contants defined in this class (<code>procedureColumnUnknown</code>,
  * <code>procedureColumnIn</code>, <code>procedureColumnInOut</code>,
  * <code>procedureColumnOut</code>, <code>procedureColumnReturn</code>,
  * or <code>procedureColumnResult</code>).
  * <li>DATA_TYPE - The SQL type of the column. This is one of the constants
  * defined in <code>Types</code>.
  * <li>TYPE_NAME - The string name of the data type for this column.
  * <li>PRECISION - The precision of the column.
  * <li>LENGTH - The length of the column in bytes
  * <li>SCALE - The scale of the column.
  * <li>RADIX - The radix of the column.
  * <li>NULLABLE - Whether or not the column is NULLABLE.  This is one of
  * the constants defined in this class (<code>procedureNoNulls</code>,
  * <code>procedureNullable</code>, or <code>procedureNullableUnknown</code>)
  * <li>REMARKS - A description of the column.
  * </ol>
  *
  * @param catalog The name of the catalog to return stored procedured from,
  * or "" to return procedures from all catalogs.
  * @param schemaPattern A schema pattern for the schemas to return stored
  * procedures from, or "" to return procedures from all schemas.
  * @param namePattern The pattern of procedures names to return.
  * @param columnPattern The pattern of column names to return.
  *
  * @returns A <code>ResultSet</code> with all the requested procedures.
  *
  * @exception SQLException If an error occurs.
  */
public abstract ResultSet
getProcedureColumns(String catalog, String schemaPattern, String namePattern,
                    String columnPattern) throws SQLException;

/*************************************************************************/

/**
  * This method returns a list of the requested table as a   
  * <code>ResultSet</code> with the following columns:
  * <p>
  * <ol>
  * <li>TABLE_CAT - The catalog the table is in, which may be <code>null</code>.
  * <li>TABLE_SCHEM - The schema the table is in, which may be <code>null</code>.
  * <li>TABLE_NAME - The name of the table.
  * <li>TABLE_TYPE - A string describing the table type.  This will be one
  * of the values returned by the <code>getTableTypes()</code> method.
  * <li>REMARKS - Comments about the table.
  * </ol>
  * 
  * @param catalog The name of the catalog to return tables from,
  * or "" to return tables from all catalogs.
  * @param schemaPattern A schema pattern for the schemas to return tables
  * from, or "" to return tables from all schemas.
  * @param namePattern The pattern of table names to return.
  * @param types The list of table types to include; null returns all types.
  *
  * @returns A <code>ResultSet</code> with all the requested tables.
  *
  * @exception SQLException If an error occurs.
  */
public abstract ResultSet
getTables(String catalog, String schemaPattern, String namePattern,
	  String types[]) throws SQLException;

/*************************************************************************/

/**
  * This method returns the list of database schemas as a 
  * <code>ResultSet</code>, with one column - TABLE_SCHEM - that is the
  * name of the schema.
  *
  * @return A <code>ResultSet</code> with all the requested schemas.
  *
  * @exception SQLException If an error occurs.
  */
public abstract ResultSet
getSchemas() throws SQLException;

/*************************************************************************/

/**
  * This method returns the list of database catalogs as a
  * <code>ResultSet</code> with one column - TABLE_CAT - that is the
  * name of the catalog.
  *
  * @return A <code>ResultSet</code> with all the requested catalogs.
  *
  * @exception SQLException If an error occurs.
  */
public abstract ResultSet
getCatalogs() throws SQLException;

/*************************************************************************/

/**
  * This method returns the list of database table types as a
  * <code>ResultSet</code> with one column - TABLE_TYPE - that is the
  * name of the table type.
  *
  * @return A <code>ResultSet</code> with all the requested table types.
  *
  * @exception SQLException If an error occurs.
  */
public abstract ResultSet
getTableTypes() throws SQLException;

/*************************************************************************/

/**
  * This method returns a list of the tables columns for
  * the requested tables.  This is returned in the form of a
  * <code>ResultSet</code> with the following columns:
  * <p>
  * <ol>
  * <li>TABLE_CAT - The catalog the table is in, which may be 
  * <code>null</code>.
  * <li>TABLE_SCHEM - The schema the tables is in, which may be
  * <code>null</code>.
  * <li>TABLE_NAME - The name of the table.
  * <li>COLUMN_NAME - The name of the column
  * <li>DATA_TYPE - The SQL type of the column. This is one of the constants
  * defined in <code>Types</code>.
  * <li>TYPE_NAME - The string name of the data type for this column.
  * <li>COLUMN_SIZE - The size of the column.
  * <li>Unused
  * <li>NUM_PREC_RADIX - The radix of the column.
  * <li>NULLABLE - Whether or not the column is NULLABLE.  This is one of
  * the constants defined in this class (<code>tableNoNulls</code>,
  * <code>tableNullable</code>, or <code>tableNullableUnknown</code>)
  * <li>REMARKS - A description of the column.
  * <li>COLUMN_DEF - The default value for the column, may be <code>null</code>.
  * <li>SQL_DATA_TYPE - Unused
  * <li>SQL_DATETIME_SUB - Unused
  * <li>CHAR_OCTET_LENGTH - For character columns, the maximum number of bytes
  * in the column.
  * <li>ORDINAL_POSITION - The index of the column in the table.
  * <li>IS_NULLABLE - "NO" means no, "YES" means maybe, and an empty string
  * means unknown.
  * </ol>
  *
  * @param catalog The name of the catalog to return table from,
  * or "" to return tables from all catalogs.
  * @param schemaPattern A schema pattern for the schemas to return 
  * tables from, or "" to return tables from all schemas.
  * @param namePattern The pattern of tables names to return.
  * @param columnPattern The pattern of column names to return.
  *
  * @returns A <code>ResultSet</code> with all the requested tables.
  *
  * @exception SQLException If an error occurs.
  */
public abstract ResultSet
getColumns(String catalog, String schemaPattern, String namePattern,
           String columnPattern) throws SQLException;

/*************************************************************************/

/**
  * This method returns the access rights that have been granted to the
  * requested columns.  This information is returned as a <code>ResultSet</code>
  * with the following columns:
  * <p>
  * <ol>
  * <li>TABLE_CAT - The catalog the table is in, which may be 
  * <code>null</code>.
  * <li>TABLE_SCHEM - The schema the tables is in, which may be
  * <code>null</code>.
  * <li>TABLE_NAME - The name of the table.
  * <li>COLUMN_NAME - The name of the column.
  * <li>GRANTOR - The entity that granted the access.
  * <li>GRANTEE - The entity granted the access.
  * <li>PRIVILEGE - The name of the privilege granted.
  * <li>IS_GRANTABLE - "YES" if the grantee can grant the privilege to
  * others, "NO" if not, and <code>null</code> if unknown.
  * </ol>
  *
  * @param catalog The catalog to retrieve information from, or the empty string
  * to return entities not associated with a catalog, or <code>null</code>
  * to return information from all catalogs.
  * @param schema The schema to retrieve information from, or the empty string
  * to return entities not associated with a schema.
  * @param table The table name to return information for.
  * @param columnPattern A pattern of column names to return information for.
  * 
  * @return A <code>ResultSet</code> with all the requested privileges.
  *
  * @exception SQLException If an error occurs.
  */
public abstract ResultSet
getColumnPrivileges(String catalog, String schema, String table,
                    String columnPattern) throws SQLException;

/*************************************************************************/

/**
  * This method returns the access rights that have been granted to the
  * requested tables.  This information is returned as a <code>ResultSet</code>
  * with the following columns:
  * <p>
  * <ol>
  * <li>TABLE_CAT - The catalog the table is in, which may be 
  * <code>null</code>.
  * <li>TABLE_SCHEM - The schema the tables is in, which may be
  * <code>null</code>.
  * <li>TABLE_NAME - The name of the table.
  * <li>GRANTOR - The entity that granted the access.
  * <li>GRANTEE - The entity granted the access.
  * <li>PRIVILEGE - The name of the privilege granted.
  * <li>IS_GRANTABLE - "YES" if the grantee can grant the privilege to
  * others, "NO" if not, and <code>null</code> if unknown.
  * </ol>
  *
  * @param catalog The catalog to retrieve information from, or the empty string
  * to return entities not associated with a catalog, or <code>null</code>
  * to return information from all catalogs.
  * @param schema The schema to retrieve information from, or the empty string
  * to return entities not associated with a schema.
  * @param tablePattern The table name pattern of tables to return 
  * information for.
  * 
  * @return A <code>ResultSet</code> with all the requested privileges.
  *
  * @exception SQLException If an error occurs.
  */
public abstract ResultSet
getTablePrivileges(String catalog, String schema, String table)
                   throws SQLException;

/*************************************************************************/

/**
  * This method returns the best set of columns for uniquely identifying
  * a row.  It returns this information as a <code>ResultSet</code> with
  * the following columns:
  * <p>
  * <ol>
  * <li>SCOPE - The scope of the results returned.  This is one of the 
  * constants defined in this class (<code>bestRowTemporary</code>,
  * <code>bestRowTransaction</code>, or <code>bestRowSession</code>).
  * <li>COLUMN_NAME - The name of the column.
  * <li>DATA_TYPE - The SQL type of the column. This is one of the constants
  * defined in <code>Types</code>.
  * <li>TYPE_NAME - The string name of the data type for this column.
  * <li>COLUMN_SIZE - The precision of the columns
  * <li>BUFFER_LENGTH - Unused
  * <li>DECIMAL_DIGITS - The scale of the column.
  * <li>PSEUDO_COLUMN - Whether or not the best row identifier is a
  * pseudo_column.  This is one of the constants defined in this class 
  * (<code>bestRowUnknown</code>, <code>bestRowNotPseudo</code>, or
  * <code>bestRowPseudo</code>).
  * </ol>
  *
  * @param catalog The catalog to retrieve information from, or the empty string
  * to return entities not associated with a catalog, or <code>null</code>
  * to return information from all catalogs.
  * @param schema The schema to retrieve information from, or the empty string
  * to return entities not associated with a schema.
  * @param table The table name to return information for.
  * @param columnPattern A pattern of column names to return information for.
  * @param scope One of the best row id scope constants from this class.
  * @param nullable <code>true</code> to include columns that are nullable,
  * <code>false</code> otherwise.
  * 
  * @return A <code>ResultSet</code> with the best row identifier.
  *
  * @exception SQLException If an error occurs.
  */
public abstract ResultSet
getBestRowIdentifier(String catalog, String schema, String table,
                     int scope, boolean nullable) throws SQLException;

/*************************************************************************/

/**
  * This method returns the set of columns that are automatically updated
  * when the row is update. It returns this information as a 
  * <code>ResultSet</code> with the following columns:
  * <p>
  * <ol>
  * <li>SCOPE - Unused
  * <li>COLUMN_NAME - The name of the column.
  * <li>DATA_TYPE - The SQL type of the column. This is one of the constants
  * defined in <code>Types</code>.
  * <li>TYPE_NAME - The string name of the data type for this column.
  * <li>COLUMN_SIZE - The precision of the columns
  * <li>BUFFER_LENGTH - Unused
  * <li>DECIMAL_DIGITS - The scale of the column.
  * <li>PSEUDO_COLUMN - Whether or not the best row identifier is a
  * pseudo_column.  This is one of the constants defined in this class 
  * (<code>versionRowUnknown</code>, <code>versionRowNotPseudo</code>, or
  * <code>versionRowPseudo</code>).
  * </ol>
  *
  * @param catalog The catalog to retrieve information from, or the empty string
  * to return entities not associated with a catalog, or <code>null</code>
  * to return information from all catalogs.
  * @param schema The schema to retrieve information from, or the empty string
  * to return entities not associated with a schema.
  * @param table The table name to return information for.
  * @param columnPattern A pattern of column names to return information for.
  *
  * @return A <code>ResultSet</code> with the version columns.
  *
  * @exception SQLException If an error occurs.
  */
public abstract ResultSet
getVersionColumns(String catalog, String schema, String table)
                  throws SQLException;

/*************************************************************************/

/**
  * This method returns a list of a table's primary key columns.  These
  * are returned as a <code>ResultSet</code> with the following columns.
  * <p>
  * <ol>
  * <li>TABLE_CAT - The catalog of the table, which may be <code>null</code>.
  * <li>TABLE_SCHEM - The schema of the table, which may be <code>null</code>.
  * <li>TABLE_NAME - The name of the table.
  * <li>COLUMN_NAME - The name of the column.
  * <li>KEY_SEQ - The sequence number of the column within the primary key.
  * <li>PK_NAME - The name of the primary key, which may be <code>null</code>.
  * </ol>
  *
  * @param catalog The catalog to retrieve information from, or the empty string
  * to return entities not associated with a catalog, or <code>null</code>
  * to return information from all catalogs.
  * @param schema The schema to retrieve information from, or the empty string
  * to return entities not associated with a schema.
  * @param table The table name to return information for.
  * @param columnPattern A pattern of column names to return information for.
  *
  * @return A <code>ResultSet</code> with the primary key columns.
  *
  * @exception SQLException If an error occurs.
  */
public abstract ResultSet
getPrimaryKeys(String catalog, String schema, String table)
               throws SQLException;

/*************************************************************************/

/**
  * This method returns a list of the table's foreign keys.  These are
  * returned as a <code>ResultSet</code> with the following columns:
  * <p>
  * <ol>
  * <li>PKTABLE_CAT - The catalog of the table the key was imported from.
  * <li>PKTABLE_SCHEM - The schema of the table the key was imported from.
  * <li>PKTABLE_NAME - The name of the table the key was imported from.
  * <li>PKCOLUMN_NAME - The name of the column that was imported.
  * <li>FKTABLE_CAT - The foreign key catalog name.
  * <li>FKTABLE_SCHEM - The foreign key schema name.
  * <li>FKTABLE_NAME - The foreign key table name.
  * <li>FKCOLUMN_NAME - The foreign key column name.
  * <li>KEY_SEQ - The sequence number of the column within the foreign key.
  * <li>UPDATE_RULE - How the foreign key behaves when the primary key is
  * updated.  This is one of the constants defined in this class 
  * (<code>importedNoAction</code>, <code>importedKeyCascade</code>,
  * <code>importedKeySetNull</code>, <code>importedKeySetDefault</code>, or
  * <code>importedKeyRestrict</code>).
  * <li>DELETE_RULE - How the foreign key behaves when the primary key is
  * deleted.  This is one of the constants defined in this class 
  * (<code>importedNoAction</code>, <code>importedKeyCascade</code>,
  * <code>importedKeySetNull</code>, or <code>importedKeySetDefault</code>)
  * <li>FK_NAME - The name of the foreign key.
  * <li>PK_NAME - The name of the primary key.
  * <li>DEFERRABILITY - The deferrability value.  This is one of the
  * constants defined in this table (<code>importedKeyInitiallyDeferred</code>,
  * <code>importedKeyInitiallyImmediate</code>, or
  * <code>importedKeyNotDeferrable</code>).
  * </ol>
  *
  * @param catalog The catalog to retrieve information from, or the empty string
  * to return entities not associated with a catalog, or <code>null</code>
  * to return information from all catalogs.
  * @param schema The schema to retrieve information from, or the empty string
  * to return entities not associated with a schema.
  * @param table The table name to return information for.
  *
  * @return A <code>ResultSet</code> with the foreign key columns.
  *
  * @exception SQLException If an error occurs.
  */
public abstract ResultSet
getImportedKeys(String catalog, String schema, String table)
                throws SQLException;

/*************************************************************************/

/**
  * This method returns a list of the table's which use this table's
  * primary key as a foreign key.  The information is
  * returned as a <code>ResultSet</code> with the following columns:
  * <p>
  * <ol>
  * <li>PKTABLE_CAT - The catalog of the table the key was imported from.
  * <li>PKTABLE_SCHEM - The schema of the table the key was imported from.
  * <li>PKTABLE_NAME - The name of the table the key was imported from.
  * <li>PKCOLUMN_NAME - The name of the column that was imported.
  * <li>FKTABLE_CAT - The foreign key catalog name.
  * <li>FKTABLE_SCHEM - The foreign key schema name.
  * <li>FKTABLE_NAME - The foreign key table name.
  * <li>FKCOLUMN_NAME - The foreign key column name.
  * <li>KEY_SEQ - The sequence number of the column within the foreign key.
  * <li>UPDATE_RULE - How the foreign key behaves when the primary key is
  * updated.  This is one of the constants defined in this class 
  * (<code>importedNoAction</code>, <code>importedKeyCascade</code>,
  * <code>importedKeySetNull</code>, <code>importedKeySetDefault</code>, or
  * <code>importedKeyRestrict</code>).
  * <li>DELETE_RULE - How the foreign key behaves when the primary key is
  * deleted.  This is one of the constants defined in this class 
  * (<code>importedNoAction</code>, <code>importedKeyCascade</code>,
  * <code>importedKeySetNull</code>, or <code>importedKeySetDefault</code>)
  * <li>FK_NAME - The name of the foreign key.
  * <li>PK_NAME - The name of the primary key.
  * <li>DEFERRABILITY - The deferrability value.  This is one of the
  * constants defined in this table (<code>importedKeyInitiallyDeferred</code>,
  * <code>importedKeyInitiallyImmediate</code>, or
  * <code>importedKeyNotDeferrable</code>).
  * </ol>
  *
  * @param catalog The catalog to retrieve information from, or the empty string
  * to return entities not associated with a catalog, or <code>null</code>
  * to return information from all catalogs.
  * @param schema The schema to retrieve information from, or the empty string
  * to return entities not associated with a schema.
  * @param table The table name to return information for.
  *
  * @return A <code>ResultSet</code> with the requested information
  *
  * @exception SQLException If an error occurs.
  */
public abstract ResultSet
getExportedKeys(String catalog, String schema, String table)
                throws SQLException;

/*************************************************************************/

/**
  * This method returns a description of how one table imports another
  * table's primary key as a foreign key.  The information is
  * returned as a <code>ResultSet</code> with the following columns:
  * <p>
  * <ol>
  * <li>PKTABLE_CAT - The catalog of the table the key was imported from.
  * <li>PKTABLE_SCHEM - The schema of the table the key was imported from.
  * <li>PKTABLE_NAME - The name of the table the key was imported from.
  * <li>PKCOLUMN_NAME - The name of the column that was imported.
  * <li>FKTABLE_CAT - The foreign key catalog name.
  * <li>FKTABLE_SCHEM - The foreign key schema name.
  * <li>FKTABLE_NAME - The foreign key table name.
  * <li>FKCOLUMN_NAME - The foreign key column name.
  * <li>KEY_SEQ - The sequence number of the column within the foreign key.
  * <li>UPDATE_RULE - How the foreign key behaves when the primary key is
  * updated.  This is one of the constants defined in this class 
  * (<code>importedNoAction</code>, <code>importedKeyCascade</code>,
  * <code>importedKeySetNull</code>, <code>importedKeySetDefault</code>, or
  * <code>importedKeyRestrict</code>).
  * <li>DELETE_RULE - How the foreign key behaves when the primary key is
  * deleted.  This is one of the constants defined in this class 
  * (<code>importedNoAction</code>, <code>importedKeyCascade</code>,
  * <code>importedKeySetNull</code>, or <code>importedKeySetDefault</code>)
  * <li>FK_NAME - The name of the foreign key.
  * <li>PK_NAME - The name of the primary key.
  * <li>DEFERRABILITY - The deferrability value.  This is one of the
  * constants defined in this table (<code>importedKeyInitiallyDeferred</code>,
  * <code>importedKeyInitiallyImmediate</code>, or
  * <code>importedKeyNotDeferrable</code>).
  * </ol>
  *
  * @param primCatalog The catalog to retrieve information from, or the empty string
  * to return entities not associated with a catalog, or <code>null</code>
  * to return information from all catalogs, on the exporting side.
  * @param primSchema The schema to retrieve information from, or the empty string
  * to return entities not associated with a schema, on the exporting side.
  * @param primTable The table name to return information for, on the exporting
  * side.
  * @param forCatalog The catalog to retrieve information from, or the empty string
  * to return entities not associated with a catalog, or <code>null</code>
  * to return information from all catalogs, on the importing side.
  * @param forSchema The schema to retrieve information from, or the empty string
  * to return entities not associated with a schema on the importing side.
  * @param forTable The table name to return information for on the importing
  * side.
  *
  * @return A <code>ResultSet</code> with the requested information
  *
  * @exception SQLException If an error occurs.
  */
public abstract ResultSet
getCrossReference(String primCatalog, String primSchema, String primTable,
                  String forCatalog, String forSchema, String forTable)
                  throws SQLException;

/*************************************************************************/

/**
  * This method returns a list of the SQL types supported by this
  * database.  The information is returned as a <code>ResultSet</code>
  * with the following columns:
  * <p>
  * <ol>
  * <li>TYPE_NAME - The name of the data type.
  * <li>DATA_TYPE - A data type constant from <code>Types</code> for this
  * type.
  * <li>PRECISION - The maximum precision of this type.
  * <li>LITERAL_PREFIX - Prefix value used to quote a literal, which may be
  * <code>null</code>.
  * <li>LITERAL_SUFFIX - Suffix value used to quote a literal, which may be
  * <code>null</code>.
  * <li>CREATE_PARAMS - The parameters used to create the type, which may be
  * <code>null</code>.
  * <li>NULLABLE - Whether or not this type supports NULL values.  This will
  * be one of the constants defined in this interface 
  * (<code>typeNoNulls</code>, <code>typeNullable</code>, or
  * <code>typeNullableUnknown</code>).
  * <li>CASE_SENSITIVE - Whether or not the value is case sensitive.
  * <li>SEARCHABLE - Whether or not "LIKE" expressions are supported in
  * WHERE clauses for this type.  This will be one of the constants defined
  * in this interface (<code>typePredNone</code>, <code>typePredChar</code>,
  * <code>typePredBasic</code>, or <code>typeSearchable</code>).
  * <li>UNSIGNED_ATTRIBUTE - Is the value of this type unsigned.
  * <li>FIXED_PREC_SCALE - Whether or not this type can be used for money.
  * <li>AUTO_INCREMENT - Whether or not this type supports auto-incrementing.
  * <li>LOCAL_TYPE_NAME - A localized name for this data type.
  * <li>MINIMUM_SCALE - The minimum scale supported by this type.
  * <li>MAXIMUM_SCALE - The maximum scale supported by this type.
  * <li>SQL_DATA_TYPE - Unused.
  * <li>SQL_DATETIME_SUB - Unused.
  * <li>NUM_PREC_RADIX - The radix of this data type.
  * </ol>
  * 
  * @return A <code>ResultSet</code> with the list of available data types.
  *
  * @exception SQLException If an error occurs.
  */
public abstract ResultSet
getTypeInfo() throws SQLException;

/*************************************************************************/

/**
  * This method returns information about a tables indices and statistics.
  * It is returned as a <code>ResultSet</code> with the following columns:
  * <p>
  * <ol>
  * <li>TABLE_CAT - The catalog of the table, which may be <code>null</code>.
  * <li>TABLE_SCHEM - The schema of the table, which may be <code>null</code>.
  * <li>TABLE_NAME - The name of the table.
  * <li>NON_UNIQUE - Are index values non-unique?
  * <li>INDEX_QUALIFIER The index catalog, which may be <code>null</code>
  * <li>INDEX_NAME - The name of the index.
  * <li>TYPE - The type of index, which will be one of the constants defined
  * in this interface (<code>tableIndexStatistic</code>,
  * <code>tableIndexClustered</code>, <code>tableIndexHashed</code>, or
  * <code>tableIndexOther</code>).
  * <li>ORDINAL_POSITION - The sequence number of this column in the index.
  * This will be 0 when the index type is <code>tableIndexStatistic</code>.
  * <li>COLUMN_NAME - The name of this column in the index.
  * <li>ASC_OR_DESC - "A" for an ascending sort sequence, "D" for a
  * descending sort sequence or <code>null</code> if a sort sequence is not
  * supported.
  * <li>CARDINALITY - The number of unique rows in the index, or the number
  * of rows in the table if the index type is <code>tableIndexStatistic</code>.
  * <li>PAGES - The number of pages used for the index, or the number of pages
  * in the table if the index type is <code>tableIndexStatistic</code>.
  * <li>FILTER_CONDITION - The filter condition for this index, which may be
  * <code>null</code>.
  * </ol>
  *
  * @param catalog The catalog to retrieve information from, or the empty string
  * to return entities not associated with a catalog, or <code>null</code>
  * to return information from all catalogs.
  * @param schema The schema to retrieve information from, or the empty string
  * to return entities not associated with a schema.
  * @param table The table name to return information for.
  * @param unique <code>true</code> to return only unique indexes, 
  * <code>false</code> otherwise.
  * @param approx <code>true</code> if data values can be approximations,
  * <code>false</code> otherwise.
  *
  * @return A <code>ResultSet</code> with the requested index information
  *
  * @exception SQLException If an error occurs.
  */
public abstract ResultSet
getIndexInfo(String catalog, String schema, String table, boolean unique,
             boolean approx) throws SQLException; 

/*************************************************************************/

/**
  * This method tests whether or not the datbase supports the specified
  * result type.
  *
  * @param type The desired result type, which is one of the constants
  * defined in <code>ResultSet</code>.
  *
  * @return <code>true</code> if the result set type is supported,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  *
  * @see ResultSet
  */
public abstract boolean
supportsResultSetType(int type) throws SQLException;

/*************************************************************************/

/**
  * This method tests whether the specified result set type and result set
  * concurrency type are supported by the database.
  *
  * @param type The desired result type, which is one of the constants
  * defined in <code>ResultSet</code>.
  * @param concur The desired concurrency type, which is one of the constants
  * defined in <code>ResultSet</code>.
  *
  * @return <code>true</code> if the result set type is supported,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  *
  * @see ResultSet
  */
public abstract boolean
supportsResultSetConcurrency(int type, int concur) throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the specified result set type sees its
  * own updates.
  *
  * @param type The desired result type, which is one of the constants
  * defined in <code>ResultSet</code>.
  *
  * @return <code>true</code> if the result set type sees its own updates,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  *
  * @see ResultSet
  */
public abstract boolean
ownUpdatesAreVisible(int type) throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the specified result set type sees its
  * own deletes.
  *
  * @param type The desired result type, which is one of the constants
  * defined in <code>ResultSet</code>.
  *
  * @return <code>true</code> if the result set type sees its own deletes,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  *
  * @see ResultSet
  */
public abstract boolean
ownDeletesAreVisible(int type) throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the specified result set type sees its
  * own inserts.
  *
  * @param type The desired result type, which is one of the constants
  * defined in <code>ResultSet</code>.
  *
  * @return <code>true</code> if the result set type sees its own inserts,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  *
  * @see ResultSet
  */
public abstract boolean
ownInsertsAreVisible(int type) throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the specified result set type sees 
  * updates committed by others.
  *
  * @param type The desired result type, which is one of the constants
  * defined in <code>ResultSet</code>.
  *
  * @return <code>true</code> if the result set type sees other updates,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  *
  * @see ResultSet
  */
public abstract boolean
othersUpdatesAreVisible(int type) throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the specified result set type sees 
  * deletes committed by others.
  *
  * @param type The desired result type, which is one of the constants
  * defined in <code>ResultSet</code>.
  *
  * @return <code>true</code> if the result set type sees other deletes,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  *
  * @see ResultSet
  */
public abstract boolean
othersDeletesAreVisible(int type) throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the specified result set type sees 
  * inserts committed by others.
  *
  * @param type The desired result type, which is one of the constants
  * defined in <code>ResultSet</code>.
  *
  * @return <code>true</code> if the result set type sees other inserts,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  *
  * @see ResultSet
  */
public abstract boolean
othersInsertsAreVisible(int type) throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the specified result set type can detect
  * a visible update by calling the <code>rowUpdated</code> method.
  *
  * @param type The desired result type, which is one of the constants
  * defined in <code>ResultSet</code>.
  *
  * @return <code>true</code> if the result set type can detect visible updates
  * using <code>rowUpdated</code>, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  *
  * @see ResultSet
  */
public abstract boolean
updatesAreDetected(int type) throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the specified result set type can detect
  * a visible delete by calling the <code>rowUpdated</code> method.
  *
  * @param type The desired result type, which is one of the constants
  * defined in <code>ResultSet</code>.
  *
  * @return <code>true</code> if the result set type can detect visible deletes
  * using <code>rowUpdated</code>, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  *
  * @see ResultSet
  */
public abstract boolean
deletesAreDetected(int type) throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the specified result set type can detect
  * a visible insert by calling the <code>rowUpdated</code> method.
  *
  * @param type The desired result type, which is one of the constants
  * defined in <code>ResultSet</code>.
  *
  * @return <code>true</code> if the result set type can detect visible inserts
  * using <code>rowUpdated</code>, <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  *
  * @see ResultSet
  */
public abstract boolean
insertsAreDetected(int type) throws SQLException;

/*************************************************************************/

/**
  * This method tests whether or not the database supports batch updates.
  *
  * @return <code>true</code> if batch updates are supported,
  * <code>false</code> otherwise.
  *
  * @exception SQLException If an error occurs.
  */
public abstract boolean
supportsBatchUpdates() throws SQLException;

/*************************************************************************/

/**
  * This method returns the list of user defined data types in use.  These
  * are returned as a <code>ResultSet</code> with the following columns:
  * <p>
  * <ol>
  * <li>TYPE_CAT - The catalog name, which may be <code>null</code>.
  * <li>TYPE_SCEHM - The schema name, which may be <code>null</code>.
  * <li>TYPE_NAME - The user defined data type name.
  * <li>CLASS_NAME - The Java class name this type maps to.
  * <li>DATA_TYPE - A type identifier from <code>Types</code> for this type.
  * This will be one of <code>JAVA_OBJECT</code>, <code>STRUCT</code>, or
  * <code>DISTINCT</code>.
  * <li>REMARKS - Comments about this data type.
  * </ol>
  *
  * @param catalog The catalog to retrieve information from, or the empty string
  * to return entities not associated with a catalog, or <code>null</code>
  * to return information from all catalogs.
  * @param schema The schema to retrieve information from, or the empty string
  * to return entities not associated with a schema.
  * @param typePattern The type name pattern to match.
  * @param types The type identifier patterns (from <code>Types</code>) to
  * match.
  *
  * @return A <code>ResultSet</code> with the requested type information
  *
  * @exception SQLException If an error occurs.
  */
public abstract ResultSet
getUDTs(String catalog, String schema, String typePattern, int[] types)
        throws SQLException;

/*************************************************************************/

/**
  * This method returns the <code>Connection</code> object that was used
  * to generate the metadata in this object.
  *
  * @return The connection for this object.
  *
  * @exception SQLException If an error occurs.
  */
public abstract Connection
getConnection() throws SQLException;

} // interface DatabaseMetaData

. This may * be null. * * @see #getCursor() * @see #setCursor(Cursor) */ Cursor cursor; /** * The locale for the component. * * @see #getLocale() * @see #setLocale(Locale) */ Locale locale = Locale.getDefault (); /** * True if the object should ignore repaint events (usually because it is * not showing). * * @see #getIgnoreRepaint() * @see #setIgnoreRepaint(boolean) * @serial true to ignore repaints * @since 1.4 */ boolean ignoreRepaint; /** * True when the object is visible (although it is only showing if all * ancestors are likewise visible). For component, this defaults to true. * * @see #isVisible() * @see #setVisible(boolean) * @serial true if visible */ boolean visible = true; /** * True if the object is enabled, meaning it can interact with the user. * For component, this defaults to true. * * @see #isEnabled() * @see #setEnabled(boolean) * @serial true if enabled */ boolean enabled = true; /** * True if the object is valid. This is set to false any time a size * adjustment means the component need to be layed out again. * * @see #isValid() * @see #validate() * @see #invalidate() * @serial true if layout is valid */ boolean valid; /** * The DropTarget for drag-and-drop operations. * * @see #getDropTarget() * @see #setDropTarget(DropTarget) * @serial the drop target, or null * @since 1.2 */ DropTarget dropTarget; /** * The list of popup menus for this component. * * @see #add(PopupMenu) * @serial the list of popups */ Vector popups; /** * The component's name. May be null, in which case a default name is * generated on the first use. * * @see #getName() * @see #setName(String) * @serial the name */ String name; /** * True once the user has set the name. Note that the user may set the name * to null. * * @see #name * @see #getName() * @see #setName(String) * @serial true if the name has been explicitly set */ boolean nameExplicitlySet; /** * Indicates if the object can be focused. Defaults to true for components. * * @see #isFocusable() * @see #setFocusable(boolean) * @since 1.4 */ boolean focusable = true; /** * Tracks whether this component's {@link #isFocusTraversable} * method has been overridden. * * @since 1.4 */ int isFocusTraversableOverridden; /** * The focus traversal keys, if not inherited from the parent or * default keyboard focus manager. These sets will contain only * AWTKeyStrokes that represent press and release events to use as * focus control. * * @see #getFocusTraversalKeys(int) * @see #setFocusTraversalKeys(int, Set) * @since 1.4 */ Set[] focusTraversalKeys; /** * True if focus traversal keys are enabled. This defaults to true for * Component. If this is true, keystrokes in focusTraversalKeys are trapped * and processed automatically rather than being passed on to the component. * * @see #getFocusTraversalKeysEnabled() * @see #setFocusTraversalKeysEnabled(boolean) * @since 1.4 */ boolean focusTraversalKeysEnabled = true; /** * Cached information on the minimum size. Should have been transient. * * @serial ignore */ Dimension minSize; /** * Flag indicating whether the minimum size for the component has been set * by a call to {@link #setMinimumSize(Dimension)} with a non-null value. */ boolean minSizeSet; /** * The maximum size for the component. * @see #setMaximumSize(Dimension) */ Dimension maxSize; /** * A flag indicating whether the maximum size for the component has been set * by a call to {@link #setMaximumSize(Dimension)} with a non-null value. */ boolean maxSizeSet; /** * Cached information on the preferred size. Should have been transient. * * @serial ignore */ Dimension prefSize; /** * Flag indicating whether the preferred size for the component has been set * by a call to {@link #setPreferredSize(Dimension)} with a non-null value. */ boolean prefSizeSet; /** * Set to true if an event is to be handled by this component, false if * it is to be passed up the hierarcy. * * @see #dispatchEvent(AWTEvent) * @serial true to process event locally */ boolean newEventsOnly; /** * Set by subclasses to enable event handling of particular events, and * left alone when modifying listeners. For component, this defaults to * enabling only input methods. * * @see #enableInputMethods(boolean) * @see AWTEvent * @serial the mask of events to process */ long eventMask = AWTEvent.INPUT_ENABLED_EVENT_MASK; /** * Describes all registered PropertyChangeListeners. * * @see #addPropertyChangeListener(PropertyChangeListener) * @see #removePropertyChangeListener(PropertyChangeListener) * @see #firePropertyChange(String, Object, Object) * @serial the property change listeners * @since 1.2 */ PropertyChangeSupport changeSupport; /** * True if the component has been packed (layed out). * * @serial true if this is packed */ boolean isPacked; /** * The serialization version for this class. Currently at version 4. * * XXX How do we handle prior versions? * * @serial the serialization version */ int componentSerializedDataVersion = 4; /** * The accessible context associated with this component. This is only set * by subclasses. * * @see #getAccessibleContext() * @serial the accessibility context * @since 1.2 */ AccessibleContext accessibleContext; // Guess what - listeners are special cased in serialization. See // readObject and writeObject. /** Component listener chain. */ transient ComponentListener componentListener; /** Focus listener chain. */ transient FocusListener focusListener; /** Key listener chain. */ transient KeyListener keyListener; /** Mouse listener chain. */ transient MouseListener mouseListener; /** Mouse motion listener chain. */ transient MouseMotionListener mouseMotionListener; /** * Mouse wheel listener chain. * * @since 1.4 */ transient MouseWheelListener mouseWheelListener; /** * Input method listener chain. * * @since 1.2 */ transient InputMethodListener inputMethodListener; /** * Hierarcy listener chain. * * @since 1.3 */ transient HierarchyListener hierarchyListener; /** * Hierarcy bounds listener chain. * * @since 1.3 */ transient HierarchyBoundsListener hierarchyBoundsListener; // Anything else is non-serializable, and should be declared "transient". /** The parent. */ transient Container parent; /** The associated native peer. */ transient ComponentPeer peer; /** The preferred component orientation. */ transient ComponentOrientation componentOrientation = ComponentOrientation.UNKNOWN; /** * The associated graphics configuration. * * @since 1.4 */ transient GraphicsConfiguration graphicsConfig; /** * The buffer strategy for repainting. * * @since 1.4 */ transient BufferStrategy bufferStrategy; /** * The number of hierarchy listeners of this container plus all of its * children. This is needed for efficient handling of HierarchyEvents. * These must be propagated to all child components with HierarchyListeners * attached. To avoid traversal of the whole subtree, we keep track of * the number of HierarchyListeners here and only walk the paths that * actually have listeners. */ int numHierarchyListeners; int numHierarchyBoundsListeners; /** * true if requestFocus was called on this component when its * top-level ancestor was not focusable. */ private transient FocusEvent pendingFocusRequest = null; /** * The system properties that affect image updating. */ private static transient boolean incrementalDraw; private static transient Long redrawRate; static { incrementalDraw = Boolean.getBoolean ("awt.image.incrementalDraw"); redrawRate = Long.getLong ("awt.image.redrawrate"); } // Public and protected API. /** * Default constructor for subclasses. When Component is extended directly, * it forms a lightweight component that must be hosted in an opaque native * container higher in the tree. */ protected Component() { // Nothing to do here. } /** * Returns the name of this component. * * @return the name of this component * @see #setName(String) * @since 1.1 */ public String getName() { if (name == null && ! nameExplicitlySet) name = generateName(); return name; } /** * Sets the name of this component to the specified name (this is a bound * property with the name 'name'). * * @param name the new name (<code>null</code> permitted). * @see #getName() * @since 1.1 */ public void setName(String name) { nameExplicitlySet = true; String old = this.name; this.name = name; firePropertyChange("name", old, name); } /** * Returns the parent of this component. * * @return the parent of this component */ public Container getParent() { return parent; } /** * Returns the native windowing system peer for this component. Only the * platform specific implementation code should call this method. * * @return the peer for this component * @deprecated user programs should not directly manipulate peers; use * {@link #isDisplayable()} instead */ // Classpath's Gtk peers rely on this. public ComponentPeer getPeer() { return peer; } /** * Set the associated drag-and-drop target, which receives events when this * is enabled. * * @param dt the new drop target * @see #isEnabled() */ public void setDropTarget(DropTarget dt) { this.dropTarget = dt; if (peer != null) dropTarget.addNotify(peer); } /** * Gets the associated drag-and-drop target, if there is one. * * @return the drop target */ public DropTarget getDropTarget() { return dropTarget; } /** * Returns the graphics configuration of this component, if there is one. * If it has not been set, it is inherited from the parent. * * @return the graphics configuration, or null * @since 1.3 */ public GraphicsConfiguration getGraphicsConfiguration() { GraphicsConfiguration conf = null; synchronized (getTreeLock()) { if (graphicsConfig != null) { conf = graphicsConfig; } else { Component par = getParent(); if (par != null) { conf = parent.getGraphicsConfiguration(); } } } return conf; } /** * Returns the object used for synchronization locks on this component * when performing tree and layout functions. * * @return the synchronization lock for this component */ public final Object getTreeLock() { return treeLock; } /** * Returns the toolkit in use for this component. The toolkit is associated * with the frame this component belongs to. * * @return the toolkit for this component */ public Toolkit getToolkit() { // Only heavyweight peers can handle this. ComponentPeer p = peer; Component comp = this; while (p instanceof LightweightPeer) { comp = comp.parent; p = comp == null ? null : comp.peer; } Toolkit tk = null; if (p != null) { tk = peer.getToolkit(); } if (tk == null) tk = Toolkit.getDefaultToolkit(); return tk; } /** * Tests whether or not this component is valid. A invalid component needs * to have its layout redone. * * @return true if this component is valid * @see #validate() * @see #invalidate() */ public boolean isValid() { // Tests show that components are invalid as long as they are not showing, even after validate() // has been called on them. return peer != null && valid; } /** * Tests if the component is displayable. It must be connected to a native * screen resource. This reduces to checking that peer is not null. A * containment hierarchy is made displayable when a window is packed or * made visible. * * @return true if the component is displayable * @see Container#add(Component) * @see Container#remove(Component) * @see Window#pack() * @see Window#show() * @see Window#dispose() * @since 1.2 */ public boolean isDisplayable() { return peer != null; } /** * Tests whether or not this component is visible. Except for top-level * frames, components are initially visible. * * @return true if the component is visible * @see #setVisible(boolean) */ public boolean isVisible() { return visible; } /** * Tests whether or not this component is actually being shown on * the screen. This will be true if and only if it this component is * visible and its parent components are all visible. * * @return true if the component is showing on the screen * @see #setVisible(boolean) */ public boolean isShowing() { Component par = parent; return visible && peer != null && (par == null || par.isShowing()); } /** * Tests whether or not this component is enabled. Components are enabled * by default, and must be enabled to receive user input or generate events. * * @return true if the component is enabled * @see #setEnabled(boolean) */ public boolean isEnabled() { return enabled; } /** * Enables or disables this component. The component must be enabled to * receive events (except that lightweight components always receive mouse * events). * * @param enabled true to enable this component * * @see #isEnabled() * @see #isLightweight() * * @since 1.1 */ public void setEnabled(boolean enabled) { enable(enabled); } /** * Enables this component. * * @deprecated use {@link #setEnabled(boolean)} instead */ public void enable() { if (! enabled) { // Need to lock the tree here, because the peers are involved. synchronized (getTreeLock()) { enabled = true; ComponentPeer p = peer; if (p != null) p.enable(); } } } /** * Enables or disables this component. * * @param enabled true to enable this component * * @deprecated use {@link #setEnabled(boolean)} instead */ public void enable(boolean enabled) { if (enabled) enable(); else disable(); } /** * Disables this component. * * @deprecated use {@link #setEnabled(boolean)} instead */ public void disable() { if (enabled) { // Need to lock the tree here, because the peers are involved. synchronized (getTreeLock()) { enabled = false; ComponentPeer p = peer; if (p != null) p.disable(); } } } /** * Checks if this image is painted to an offscreen image buffer that is * later copied to screen (double buffering reduces flicker). This version * returns false, so subclasses must override it if they provide double * buffering. * * @return true if this is double buffered; defaults to false */ public boolean isDoubleBuffered() { return false; } /** * Enables or disables input method support for this component. By default, * components have this enabled. Input methods are given the opportunity * to process key events before this component and its listeners. * * @param enable true to enable input method processing * @see #processKeyEvent(KeyEvent) * @since 1.2 */ public void enableInputMethods(boolean enable) { if (enable) eventMask |= AWTEvent.INPUT_ENABLED_EVENT_MASK; else eventMask &= ~AWTEvent.INPUT_ENABLED_EVENT_MASK; } /** * Makes this component visible or invisible. Note that it wtill might * not show the component, if a parent is invisible. * * @param visible true to make this component visible * * @see #isVisible() * * @since 1.1 */ public void setVisible(boolean visible) { // Inspection by subclassing shows that Sun's implementation calls // show(boolean) which then calls show() or hide(). It is the show() // method that is overriden in subclasses like Window. show(visible); } /** * Makes this component visible on the screen. * * @deprecated use {@link #setVisible(boolean)} instead */ public void show() { // We must set visible before showing the peer. Otherwise the // peer could post paint events before visible is true, in which // case lightweight components are not initially painted -- // Container.paint first calls isShowing () before painting itself // and its children. if(! visible) { // Need to lock the tree here to avoid races and inconsistencies. synchronized (getTreeLock()) { visible = true; // Avoid NullPointerExceptions by creating a local reference. ComponentPeer currentPeer = peer; if (currentPeer != null) { currentPeer.show(); // Fire HierarchyEvent. fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, this, parent, HierarchyEvent.SHOWING_CHANGED); // The JDK repaints the component before invalidating the parent. // So do we. if (peer instanceof LightweightPeer) repaint(); } // Only post an event if this component actually has a listener // or has this event explicitly enabled. if (componentListener != null || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0) { ComponentEvent ce = new ComponentEvent(this,ComponentEvent.COMPONENT_SHOWN); getToolkit().getSystemEventQueue().postEvent(ce); } } // Invalidate the parent if we have one. The component itself must // not be invalidated. We also avoid NullPointerException with // a local reference here. Container currentParent = parent; if (currentParent != null) currentParent.invalidate(); } } /** * Makes this component visible or invisible. * * @param visible true to make this component visible * * @deprecated use {@link #setVisible(boolean)} instead */ public void show(boolean visible) { if (visible) show(); else hide(); } /** * Hides this component so that it is no longer shown on the screen. * * @deprecated use {@link #setVisible(boolean)} instead */ public void hide() { if (visible) { // Need to lock the tree here to avoid races and inconsistencies. synchronized (getTreeLock()) { visible = false; // Avoid NullPointerExceptions by creating a local reference. ComponentPeer currentPeer = peer; if (currentPeer != null) { currentPeer.hide(); // Fire hierarchy event. fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, this, parent, HierarchyEvent.SHOWING_CHANGED); // The JDK repaints the component before invalidating the // parent. So do we. This only applies for lightweights. if (peer instanceof LightweightPeer) repaint(); } // Only post an event if this component actually has a listener // or has this event explicitly enabled. if (componentListener != null || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0) { ComponentEvent ce = new ComponentEvent(this,ComponentEvent.COMPONENT_HIDDEN); getToolkit().getSystemEventQueue().postEvent(ce); } } // Invalidate the parent if we have one. The component itself need // not be invalidated. We also avoid NullPointerException with // a local reference here. Container currentParent = parent; if (currentParent != null) currentParent.invalidate(); } } /** * Returns this component's foreground color. If not set, this is inherited * from the parent. * * @return this component's foreground color, or null * @see #setForeground(Color) */ public Color getForeground() { if (foreground != null) return foreground; return parent == null ? null : parent.getForeground(); } /** * Sets this component's foreground color to the specified color. This is a * bound property. * * @param c the new foreground color * @see #getForeground() */ public void setForeground(Color c) { if (peer != null) peer.setForeground(c); Color previous = foreground; foreground = c; firePropertyChange("foreground", previous, c); } /** * Tests if the foreground was explicitly set, or just inherited from the * parent. * * @return true if the foreground has been set * @since 1.4 */ public boolean isForegroundSet() { return foreground != null; } /** * Returns this component's background color. If not set, this is inherited * from the parent. * * @return the background color of the component, or null * @see #setBackground(Color) */ public Color getBackground() { if (background != null) return background; return parent == null ? null : parent.getBackground(); } /** * Sets this component's background color to the specified color. The parts * of the component affected by the background color may by system dependent. * This is a bound property. * * @param c the new background color * @see #getBackground() */ public void setBackground(Color c) { // return if the background is already set to that color. if ((c != null) && c.equals(background)) return; Color previous = background; background = c; if (peer != null && c != null) peer.setBackground(c); firePropertyChange("background", previous, c); } /** * Tests if the background was explicitly set, or just inherited from the * parent. * * @return true if the background has been set * @since 1.4 */ public boolean isBackgroundSet() { return background != null; } /** * Returns the font in use for this component. If not set, this is inherited * from the parent. * * @return the font for this component * @see #setFont(Font) */ public Font getFont() { return getFontImpl(); } /** * Implementation of getFont(). This is pulled out of getFont() to prevent * client programs from overriding this. * * @return the font of this component */ private final Font getFontImpl() { Font f = font; if (f == null) { Component p = parent; if (p != null) f = p.getFontImpl(); else { // It is important to return null here and not some kind of default // font, otherwise the Swing UI would not install its fonts because // it keeps non-UIResource fonts. f = null; } } return f; } /** * Sets the font for this component to the specified font. This is a bound * property. * * @param f the new font for this component * * @see #getFont() */ public void setFont(Font f) { Font oldFont; Font newFont; // Synchronize on the tree because getFontImpl() relies on the hierarchy // not beeing changed. synchronized (getTreeLock()) { // Synchronize on this here to guarantee thread safety wrt to the // property values. synchronized (this) { oldFont = font; font = f; newFont = f; } // Create local variable here for thread safety. ComponentPeer p = peer; if (p != null) { // The peer receives the real font setting, which can depend on // the parent font when this component's font has been set to null. f = getFont(); if (f != null) { p.setFont(f); peerFont = f; } } } // Fire property change event. firePropertyChange("font", oldFont, newFont); // Invalidate when necessary as font changes can change the size of the // component. if (valid) invalidate(); } /** * Tests if the font was explicitly set, or just inherited from the parent. * * @return true if the font has been set * @since 1.4 */ public boolean isFontSet() { return font != null; } /** * Returns the locale for this component. If this component does not * have a locale, the locale of the parent component is returned. * * @return the locale for this component * @throws IllegalComponentStateException if it has no locale or parent * @see #setLocale(Locale) * @since 1.1 */ public Locale getLocale() { if (locale != null) return locale; if (parent == null) throw new IllegalComponentStateException ("Component has no parent: can't determine Locale"); return parent.getLocale(); } /** * Sets the locale for this component to the specified locale. This is a * bound property. * * @param newLocale the new locale for this component */ public void setLocale(Locale newLocale) { if (locale == newLocale) return; Locale oldLocale = locale; locale = newLocale; firePropertyChange("locale", oldLocale, newLocale); // New writing/layout direction or more/less room for localized labels. invalidate(); } /** * Returns the color model of the device this componet is displayed on. * * @return this object's color model * @see Toolkit#getColorModel() */ public ColorModel getColorModel() { GraphicsConfiguration config = getGraphicsConfiguration(); return config != null ? config.getColorModel() : getToolkit().getColorModel(); } /** * Returns the location of this component's top left corner relative to * its parent component. This may be outdated, so for synchronous behavior, * you should use a component listner. * * @return the location of this component * @see #setLocation(int, int) * @see #getLocationOnScreen() * @since 1.1 */ public Point getLocation() { return location (); } /** * Returns the location of this component's top left corner in screen * coordinates. * * @return the location of this component in screen coordinates * @throws IllegalComponentStateException if the component is not showing */ public Point getLocationOnScreen() { if (! isShowing()) throw new IllegalComponentStateException("component " + getClass().getName() + " not showing"); // Need to lock the tree here. We get crazy races and explosions when // the tree changes while we are trying to find the location of this // component. synchronized (getTreeLock()) { // Only a heavyweight peer can answer the question for the screen // location. So we are going through the hierarchy until we find // one and add up the offsets while doing so. int offsX = 0; int offsY = 0; ComponentPeer p = peer; Component comp = this; while (p instanceof LightweightPeer) { offsX += comp.x; offsY += comp.y; comp = comp.parent; p = comp == null ? null: comp.peer; } // Now we have a heavyweight component. assert ! (p instanceof LightweightPeer); Point loc = p.getLocationOnScreen(); loc.x += offsX; loc.y += offsY; return loc; } } /** * Returns the location of this component's top left corner relative to * its parent component. * * @return the location of this component * @deprecated use {@link #getLocation()} instead */ public Point location() { return new Point (x, y); } /** * Moves this component to the specified location, relative to the parent's * coordinates. The coordinates are the new upper left corner of this * component. * * @param x the new X coordinate of this component * @param y the new Y coordinate of this component * @see #getLocation() * @see #setBounds(int, int, int, int) */ public void setLocation(int x, int y) { move (x, y); } /** * Moves this component to the specified location, relative to the parent's * coordinates. The coordinates are the new upper left corner of this * component. * * @param x the new X coordinate of this component * @param y the new Y coordinate of this component * @deprecated use {@link #setLocation(int, int)} instead */ public void move(int x, int y) { setBounds(x, y, this.width, this.height); } /** * Moves this component to the specified location, relative to the parent's * coordinates. The coordinates are the new upper left corner of this * component. * * @param p new coordinates for this component * @throws NullPointerException if p is null * @see #getLocation() * @see #setBounds(int, int, int, int) * @since 1.1 */ public void setLocation(Point p) { setLocation(p.x, p.y); } /** * Returns the size of this object. * * @return the size of this object * @see #setSize(int, int) * @since 1.1 */ public Dimension getSize() { return size (); } /** * Returns the size of this object. * * @return the size of this object * @deprecated use {@link #getSize()} instead */ public Dimension size() { return new Dimension (width, height); } /** * Sets the size of this component to the specified width and height. * * @param width the new width of this component * @param height the new height of this component * @see #getSize() * @see #setBounds(int, int, int, int) */ public void setSize(int width, int height) { resize (width, height); } /** * Sets the size of this component to the specified value. * * @param width the new width of the component * @param height the new height of the component * @deprecated use {@link #setSize(int, int)} instead */ public void resize(int width, int height) { setBounds(this.x, this.y, width, height); } /** * Sets the size of this component to the specified value. * * @param d the new size of this component * @throws NullPointerException if d is null * @see #setSize(int, int) * @see #setBounds(int, int, int, int) * @since 1.1 */ public void setSize(Dimension d) { resize (d); } /** * Sets the size of this component to the specified value. * * @param d the new size of this component * @throws NullPointerException if d is null * @deprecated use {@link #setSize(Dimension)} instead */ public void resize(Dimension d) { resize (d.width, d.height); } /** * Returns a bounding rectangle for this component. Note that the * returned rectange is relative to this component's parent, not to * the screen. * * @return the bounding rectangle for this component * @see #setBounds(int, int, int, int) * @see #getLocation() * @see #getSize() */ public Rectangle getBounds() { return bounds (); } /** * Returns a bounding rectangle for this component. Note that the * returned rectange is relative to this component's parent, not to * the screen. * * @return the bounding rectangle for this component * @deprecated use {@link #getBounds()} instead */ public Rectangle bounds() { return new Rectangle (x, y, width, height); } /** * Sets the bounding rectangle for this component to the specified values. * Note that these coordinates are relative to the parent, not to the screen. * * @param x the X coordinate of the upper left corner of the rectangle * @param y the Y coordinate of the upper left corner of the rectangle * @param w the width of the rectangle * @param h the height of the rectangle * @see #getBounds() * @see #setLocation(int, int) * @see #setLocation(Point) * @see #setSize(int, int) * @see #setSize(Dimension) * @since 1.1 */ public void setBounds(int x, int y, int w, int h) { reshape (x, y, w, h); } /** * Sets the bounding rectangle for this component to the specified values. * Note that these coordinates are relative to the parent, not to the screen. * * @param x the X coordinate of the upper left corner of the rectangle * @param y the Y coordinate of the upper left corner of the rectangle * @param width the width of the rectangle * @param height the height of the rectangle * @deprecated use {@link #setBounds(int, int, int, int)} instead */ public void reshape(int x, int y, int width, int height) { // We need to lock the tree here, otherwise we risk races and // inconsistencies. synchronized (getTreeLock()) { int oldx = this.x; int oldy = this.y; int oldwidth = this.width; int oldheight = this.height; boolean resized = oldwidth != width || oldheight != height; boolean moved = oldx != x || oldy != y; if (resized || moved) { // Update the fields. this.x = x; this.y = y; this.width = width; this.height = height; if (peer != null) { peer.setBounds (x, y, width, height); if (resized) invalidate(); if (parent != null && parent.valid) parent.invalidate(); } // Send some events to interested listeners. notifyReshape(resized, moved); // Repaint this component and the parent if appropriate. if (parent != null && peer instanceof LightweightPeer && isShowing()) { // The parent repaints the area that we occupied before. parent.repaint(oldx, oldy, oldwidth, oldheight); // This component repaints the area that we occupy now. repaint(); } } } } /** * Sends notification to interested listeners about resizing and/or moving * the component. If this component has interested * component listeners or the corresponding event mask enabled, then * COMPONENT_MOVED and/or COMPONENT_RESIZED events are posted to the event * queue. * * @param resized true if the component has been resized, false otherwise * @param moved true if the component has been moved, false otherwise */ void notifyReshape(boolean resized, boolean moved) { // Only post an event if this component actually has a listener // or has this event explicitly enabled. if (componentListener != null || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0) { // Fire component event on this component. if (moved) { ComponentEvent ce = new ComponentEvent(this, ComponentEvent.COMPONENT_MOVED); getToolkit().getSystemEventQueue().postEvent(ce); } if (resized) { ComponentEvent ce = new ComponentEvent(this, ComponentEvent.COMPONENT_RESIZED); getToolkit().getSystemEventQueue().postEvent(ce); } } } /** * Sets the bounding rectangle for this component to the specified * rectangle. Note that these coordinates are relative to the parent, not * to the screen. * * @param r the new bounding rectangle * @throws NullPointerException if r is null * @see #getBounds() * @see #setLocation(Point) * @see #setSize(Dimension) * @since 1.1 */ public void setBounds(Rectangle r) { setBounds (r.x, r.y, r.width, r.height); } /** * Gets the x coordinate of the upper left corner. This is more efficient * than getBounds().x or getLocation().x. * * @return the current x coordinate * @since 1.2 */ public int getX() { return x; } /** * Gets the y coordinate of the upper left corner. This is more efficient * than getBounds().y or getLocation().y. * * @return the current y coordinate * @since 1.2 */ public int getY() { return y; } /** * Gets the width of the component. This is more efficient than * getBounds().width or getSize().width. * * @return the current width * @since 1.2 */ public int getWidth() { return width; } /** * Gets the height of the component. This is more efficient than * getBounds().height or getSize().height. * * @return the current width * @since 1.2 */ public int getHeight() { return height; } /** * Returns the bounds of this component. This allows reuse of an existing * rectangle, if r is non-null. * * @param r the rectangle to use, or null * @return the bounds */ public Rectangle getBounds(Rectangle r) { if (r == null) r = new Rectangle(); r.x = x; r.y = y; r.width = width; r.height = height; return r; } /** * Returns the size of this component. This allows reuse of an existing * dimension, if d is non-null. * * @param d the dimension to use, or null * @return the size */ public Dimension getSize(Dimension d) { if (d == null) d = new Dimension(); d.width = width; d.height = height; return d; } /** * Returns the location of this component. This allows reuse of an existing * point, if p is non-null. * * @param p the point to use, or null * @return the location */ public Point getLocation(Point p) { if (p == null) p = new Point(); p.x = x; p.y = y; return p; } /** * Tests if this component is opaque. All "heavyweight" (natively-drawn) * components are opaque. A component is opaque if it draws all pixels in * the bounds; a lightweight component is partially transparent if it lets * pixels underneath show through. Subclasses that guarantee that all pixels * will be drawn should override this. * * @return true if this is opaque * @see #isLightweight() * @since 1.2 */ public boolean isOpaque() { return ! isLightweight(); } /** * Return whether the component is lightweight. That means the component has * no native peer, but is displayable. This applies to subclasses of * Component not in this package, such as javax.swing. * * @return true if the component has a lightweight peer * @see #isDisplayable() * @since 1.2 */ public boolean isLightweight() { return peer instanceof LightweightPeer; } /** * Returns the component's preferred size. * * @return the component's preferred size * @see #getMinimumSize() * @see #setPreferredSize(Dimension) * @see LayoutManager */ public Dimension getPreferredSize() { return preferredSize(); } /** * Sets the preferred size that will be returned by * {@link #getPreferredSize()} always, and sends a * {@link PropertyChangeEvent} (with the property name 'preferredSize') to * all registered listeners. * * @param size the preferred size (<code>null</code> permitted). * * @since 1.5 * * @see #getPreferredSize() */ public void setPreferredSize(Dimension size) { Dimension old = prefSizeSet ? prefSize : null; prefSize = size; prefSizeSet = (size != null); firePropertyChange("preferredSize", old, size); } /** * Returns <code>true</code> if the current preferred size is not * <code>null</code> and was set by a call to * {@link #setPreferredSize(Dimension)}, otherwise returns <code>false</code>. * * @return A boolean. * * @since 1.5 */ public boolean isPreferredSizeSet() { return prefSizeSet; } /** * Returns the component's preferred size. * * @return the component's preferred size * @deprecated use {@link #getPreferredSize()} instead */ public Dimension preferredSize() { // Create a new Dimension object, so that the application doesn't mess // with the actual values. return new Dimension(preferredSizeImpl()); } /** * The actual calculation is pulled out of preferredSize() so that * we can call it from Container.preferredSize() and avoid creating a * new intermediate Dimension object. * * @return the preferredSize of the component */ Dimension preferredSizeImpl() { Dimension size = prefSize; // Try to use a cached value. if (size == null || !(valid || prefSizeSet)) { // We need to lock here, because the calculation depends on the // component structure not changing. synchronized (getTreeLock()) { ComponentPeer p = peer; if (p != null) size = peer.preferredSize(); else size = minimumSizeImpl(); } } return size; } /** * Returns the component's minimum size. * * @return the component's minimum size * @see #getPreferredSize() * @see #setMinimumSize(Dimension) * @see LayoutManager */ public Dimension getMinimumSize() { return minimumSize(); } /** * Sets the minimum size that will be returned by {@link #getMinimumSize()} * always, and sends a {@link PropertyChangeEvent} (with the property name * 'minimumSize') to all registered listeners. * * @param size the minimum size (<code>null</code> permitted). * * @since 1.5 * * @see #getMinimumSize() */ public void setMinimumSize(Dimension size) { Dimension old = minSizeSet ? minSize : null; minSize = size; minSizeSet = (size != null); firePropertyChange("minimumSize", old, size); } /** * Returns <code>true</code> if the current minimum size is not * <code>null</code> and was set by a call to * {@link #setMinimumSize(Dimension)}, otherwise returns <code>false</code>. * * @return A boolean. * * @since 1.5 */ public boolean isMinimumSizeSet() { return minSizeSet; } /** * Returns the component's minimum size. * * @return the component's minimum size * @deprecated use {@link #getMinimumSize()} instead */ public Dimension minimumSize() { // Create a new Dimension object, so that the application doesn't mess // with the actual values. return new Dimension(minimumSizeImpl()); } /** * The actual calculation is pulled out of minimumSize() so that * we can call it from Container.preferredSize() and * Component.preferredSizeImpl and avoid creating a * new intermediate Dimension object. * * @return the minimum size of the component */ Dimension minimumSizeImpl() { Dimension size = minSize; if (size == null || !(valid || minSizeSet)) { // We need to lock here, because the calculation depends on the // component structure not changing. synchronized (getTreeLock()) { ComponentPeer p = peer; if (p != null) size = peer.minimumSize(); else size = size(); } } return size; } /** * Returns the component's maximum size. * * @return the component's maximum size * @see #getMinimumSize() * @see #setMaximumSize(Dimension) * @see #getPreferredSize() * @see LayoutManager */ public Dimension getMaximumSize() { return new Dimension(maximumSizeImpl()); } /** * This is pulled out from getMaximumSize(), so that we can access it * from Container.getMaximumSize() without creating an additional * intermediate Dimension object. * * @return the maximum size of the component */ Dimension maximumSizeImpl() { Dimension size; if (maxSizeSet) size = maxSize; else size = DEFAULT_MAX_SIZE; return size; } /** * Sets the maximum size that will be returned by {@link #getMaximumSize()} * always, and sends a {@link PropertyChangeEvent} (with the property name * 'maximumSize') to all registered listeners. * * @param size the maximum size (<code>null</code> permitted). * * @since 1.5 * * @see #getMaximumSize() */ public void setMaximumSize(Dimension size) { Dimension old = maxSizeSet ? maxSize : null; maxSize = size; maxSizeSet = (size != null); firePropertyChange("maximumSize", old, size); } /** * Returns <code>true</code> if the current maximum size is not * <code>null</code> and was set by a call to * {@link #setMaximumSize(Dimension)}, otherwise returns <code>false</code>. * * @return A boolean. * * @since 1.5 */ public boolean isMaximumSizeSet() { return maxSizeSet; } /** * Returns the preferred horizontal alignment of this component. The value * returned will be between {@link #LEFT_ALIGNMENT} and * {@link #RIGHT_ALIGNMENT}, inclusive. * * @return the preferred horizontal alignment of this component */ public float getAlignmentX() { return CENTER_ALIGNMENT; } /** * Returns the preferred vertical alignment of this component. The value * returned will be between {@link #TOP_ALIGNMENT} and * {@link #BOTTOM_ALIGNMENT}, inclusive. * * @return the preferred vertical alignment of this component */ public float getAlignmentY() { return CENTER_ALIGNMENT; } /** * Calls the layout manager to re-layout the component. This is called * during validation of a container in most cases. * * @see #validate() * @see LayoutManager */ public void doLayout() { layout (); } /** * Calls the layout manager to re-layout the component. This is called * during validation of a container in most cases. * * @deprecated use {@link #doLayout()} instead */ public void layout() { // Nothing to do unless we're a container. } /** * Called to ensure that the layout for this component is valid. This is * usually called on containers. * * @see #invalidate() * @see #doLayout() * @see LayoutManager * @see Container#validate() */ public void validate() { if (! valid) { // Synchronize on the tree here as this might change the layout // of the hierarchy. synchronized (getTreeLock()) { // Create local variables for thread safety. ComponentPeer p = peer; if (p != null) { // Possibly update the peer's font. Font newFont = getFont(); Font oldFont = peerFont; // Only update when the font really changed. if (newFont != oldFont && (oldFont == null || ! oldFont.equals(newFont))) { p.setFont(newFont); peerFont = newFont; } // Let the peer perform any layout. p.layout(); } } valid = true; } } /** * Invalidates this component and all of its parent components. This will * cause them to have their layout redone. This is called frequently, so * make it fast. */ public void invalidate() { // Need to lock here, to avoid races and other ugly stuff when doing // layout or structure changes in other threads. synchronized (getTreeLock()) { // Invalidate. valid = false; // Throw away cached layout information. if (! minSizeSet) minSize = null; if (! prefSizeSet) prefSize = null; if (! maxSizeSet) maxSize = null; // Also invalidate the parent, if it hasn't already been invalidated. if (parent != null && parent.isValid()) parent.invalidate(); } } /** * Returns a graphics object for this component. Returns <code>null</code> * if this component is not currently displayed on the screen. * * @return a graphics object for this component * @see #paint(Graphics) */ public Graphics getGraphics() { // Only heavyweight peers can handle this. ComponentPeer p = peer; Graphics g = null; if (p instanceof LightweightPeer) { if (parent != null) { g = parent.getGraphics(); if (g != null) { g.translate(x, y); g.setClip(0, 0, width, height); g.setFont(getFont()); } } } else { if (p != null) g = p.getGraphics(); } return g; } /** * Returns the font metrics for the specified font in this component. * * @param font the font to retrieve metrics for * @return the font metrics for the specified font * @throws NullPointerException if font is null * @see #getFont() * @see Toolkit#getFontMetrics(Font) */ public FontMetrics getFontMetrics(Font font) { ComponentPeer p = peer; Component comp = this; while (p instanceof LightweightPeer) { comp = comp.parent; p = comp == null ? null : comp.peer; } return p == null ? getToolkit().getFontMetrics(font) : p.getFontMetrics(font); } /** * Sets the cursor for this component to the specified cursor. The cursor * is displayed when the point is contained by the component, and the * component is visible, displayable, and enabled. This is inherited by * subcomponents unless they set their own cursor. * * @param cursor the new cursor for this component * @see #isEnabled() * @see #isShowing() * @see #getCursor() * @see #contains(int, int) * @see Toolkit#createCustomCursor(Image, Point, String) */ public void setCursor(Cursor cursor) { this.cursor = cursor; // Only heavyweight peers handle this. ComponentPeer p = peer; Component comp = this; while (p instanceof LightweightPeer) { comp = comp.parent; p = comp == null ? null : comp.peer; } if (p != null) p.setCursor(cursor); } /** * Returns the cursor for this component. If not set, this is inherited * from the parent, or from Cursor.getDefaultCursor(). * * @return the cursor for this component */ public Cursor getCursor() { if (cursor != null) return cursor; return parent != null ? parent.getCursor() : Cursor.getDefaultCursor(); } /** * Tests if the cursor was explicitly set, or just inherited from the parent. * * @return true if the cursor has been set * @since 1.4 */ public boolean isCursorSet() { return cursor != null; } /** * Paints this component on the screen. The clipping region in the graphics * context will indicate the region that requires painting. This is called * whenever the component first shows, or needs to be repaired because * something was temporarily drawn on top. It is not necessary for * subclasses to call <code>super.paint(g)</code>. Components with no area * are not painted. * * @param g the graphics context for this paint job * @see #update(Graphics) */ public void paint(Graphics g) { // This is a callback method and is meant to be overridden by subclasses // that want to perform custom painting. } /** * Updates this component. This is called for heavyweight components in * response to {@link #repaint()}. The default implementation simply forwards * to {@link #paint(Graphics)}. The coordinates of the graphics are * relative to this component. Subclasses should call either * <code>super.update(g)</code> or <code>paint(g)</code>. * * @param g the graphics context for this update * * @see #paint(Graphics) * @see #repaint() */ public void update(Graphics g) { // Note 1: We used to clear the background here for lightweights and // toplevel components. Tests show that this is not what the JDK does // here. Note that there is some special handling and background // clearing code in Container.update(Graphics). // Note 2 (for peer implementors): The JDK doesn't seem call update() for // toplevel components, even when an UPDATE event is sent (as a result // of repaint). paint(g); } /** * Paints this entire component, including any sub-components. * * @param g the graphics context for this paint job * * @see #paint(Graphics) */ public void paintAll(Graphics g) { if (isShowing()) { validate(); if (peer instanceof LightweightPeer) paint(g); else peer.paint(g); } } /** * Repaint this entire component. The <code>update()</code> method * on this component will be called as soon as possible. * * @see #update(Graphics) * @see #repaint(long, int, int, int, int) */ public void repaint() { repaint(0, 0, 0, width, height); } /** * Repaint this entire component. The <code>update()</code> method on this * component will be called in approximate the specified number of * milliseconds. * * @param tm milliseconds before this component should be repainted * @see #paint(Graphics) * @see #repaint(long, int, int, int, int) */ public void repaint(long tm) { repaint(tm, 0, 0, width, height); } /** * Repaints the specified rectangular region within this component. The * <code>update</code> method on this component will be called as soon as * possible. The coordinates are relative to this component. * * @param x the X coordinate of the upper left of the region to repaint * @param y the Y coordinate of the upper left of the region to repaint * @param w the width of the region to repaint * @param h the height of the region to repaint * @see #update(Graphics) * @see #repaint(long, int, int, int, int) */ public void repaint(int x, int y, int w, int h) { repaint(0, x, y, w, h); } /** * Repaints the specified rectangular region within this component. The * <code>update</code> method on this component will be called in * approximately the specified number of milliseconds. The coordinates * are relative to this component. * * @param tm milliseconds before this component should be repainted * @param x the X coordinate of the upper left of the region to repaint * @param y the Y coordinate of the upper left of the region to repaint * @param width the width of the region to repaint * @param height the height of the region to repaint * @see #update(Graphics) */ public void repaint(long tm, int x, int y, int width, int height) { // The repaint() call has previously been delegated to // {@link ComponentPeer.repaint()}. Testing on the JDK using some // dummy peers show that this methods is never called. I think it makes // sense to actually perform the tasks below here, since it's pretty // much peer independent anyway, and makes sure only heavyweights are // bothered by this. ComponentPeer p = peer; // Let the nearest heavyweight parent handle repainting for lightweight // components. // We need to recursivly call repaint() on the parent here, since // a (lightweight) parent component might have overridden repaint() // to perform additional custom tasks. if (p instanceof LightweightPeer) { // We perform some boundary checking to restrict the paint // region to this component. if (parent != null) { int px = this.x + Math.max(0, x); int py = this.y + Math.max(0, y); int pw = Math.min(this.width, width); int ph = Math.min(this.height, height); parent.repaint(tm, px, py, pw, ph); } } else { // Now send an UPDATE event to the heavyweight component that we've found. if (isVisible() && p != null && width > 0 && height > 0) { PaintEvent pe = new PaintEvent(this, PaintEvent.UPDATE, new Rectangle(x, y, width, height)); getToolkit().getSystemEventQueue().postEvent(pe); } } } /** * Prints this component. This method is provided so that printing can be * done in a different manner from painting. However, the implementation * in this class simply calls the <code>paint()</code> method. * * @param g the graphics context of the print device * * @see #paint(Graphics) */ public void print(Graphics g) { paint(g); } /** * Prints this component, including all sub-components. * * @param g the graphics context of the print device * * @see #paintAll(Graphics) */ public void printAll(Graphics g) { if( peer != null ) peer.print( g ); paintAll( g ); } /** * Called when an image has changed so that this component is repainted. * This incrementally draws an image as more bits are available, when * possible. Incremental drawing is enabled if the system property * <code>awt.image.incrementalDraw</code> is not present or is true, in which * case the redraw rate is set to 100ms or the value of the system property * <code>awt.image.redrawrate</code>. * * <p>The coordinate system used depends on the particular flags. * * @param img the image that has been updated * @param flags tlags as specified in <code>ImageObserver</code> * @param x the X coordinate * @param y the Y coordinate * @param w the width * @param h the height * @return false if the image is completely loaded, loading has been * aborted, or an error has occurred. true if more updates are * required. * @see ImageObserver * @see Graphics#drawImage(Image, int, int, Color, ImageObserver) * @see Graphics#drawImage(Image, int, int, ImageObserver) * @see Graphics#drawImage(Image, int, int, int, int, Color, ImageObserver) * @see Graphics#drawImage(Image, int, int, int, int, ImageObserver) * @see ImageObserver#imageUpdate(Image, int, int, int, int, int) */ public boolean imageUpdate(Image img, int flags, int x, int y, int w, int h) { if ((flags & (FRAMEBITS | ALLBITS)) != 0) repaint(); else if ((flags & SOMEBITS) != 0) { if (incrementalDraw) { if (redrawRate != null) { long tm = redrawRate.longValue(); if (tm < 0) tm = 0; repaint(tm); } else repaint(100); } } return (flags & (ALLBITS | ABORT | ERROR)) == 0; } /** * Creates an image from the specified producer. * * @param producer the image procedure to create the image from * @return the resulting image */ public Image createImage(ImageProducer producer) { // Only heavyweight peers can handle this. ComponentPeer p = peer; Component comp = this; while (p instanceof LightweightPeer) { comp = comp.parent; p = comp == null ? null : comp.peer; } // Sun allows producer to be null. Image im; if (p != null) im = p.createImage(producer); else im = getToolkit().createImage(producer); return im; } /** * Creates an image with the specified width and height for use in * double buffering. Headless environments do not support images. * * @param width the width of the image * @param height the height of the image * @return the requested image, or null if it is not supported */ public Image createImage (int width, int height) { Image returnValue = null; if (!GraphicsEnvironment.isHeadless ()) { // Only heavyweight peers can handle this. ComponentPeer p = peer; Component comp = this; while (p instanceof LightweightPeer) { comp = comp.parent; p = comp == null ? null : comp.peer; } if (p != null) returnValue = p.createImage(width, height); } return returnValue; } /** * Creates an image with the specified width and height for use in * double buffering. Headless environments do not support images. * * @param width the width of the image * @param height the height of the image * @return the requested image, or null if it is not supported * @since 1.4 */ public VolatileImage createVolatileImage(int width, int height) { // Only heavyweight peers can handle this. ComponentPeer p = peer; Component comp = this; while (p instanceof LightweightPeer) { comp = comp.parent; p = comp == null ? null : comp.peer; } VolatileImage im = null; if (p != null) im = p.createVolatileImage(width, height); return im; } /** * Creates an image with the specified width and height for use in * double buffering. Headless environments do not support images. The image * will support the specified capabilities. * * @param width the width of the image * @param height the height of the image * @param caps the requested capabilities * @return the requested image, or null if it is not supported * @throws AWTException if a buffer with the capabilities cannot be created * @since 1.4 */ public VolatileImage createVolatileImage(int width, int height, ImageCapabilities caps) throws AWTException { // Only heavyweight peers can handle this. ComponentPeer p = peer; Component comp = this; while (p instanceof LightweightPeer) { comp = comp.parent; p = comp == null ? null : comp.peer; } VolatileImage im = null; if (p != null) im = peer.createVolatileImage(width, height); return im; } /** * Prepares the specified image for rendering on this component. * * @param image the image to prepare for rendering * @param observer the observer to notify of image preparation status * @return true if the image is already fully prepared * @throws NullPointerException if image is null */ public boolean prepareImage(Image image, ImageObserver observer) { return prepareImage(image, image.getWidth(observer), image.getHeight(observer), observer); } /** * Prepares the specified image for rendering on this component at the * specified scaled width and height * * @param image the image to prepare for rendering * @param width the scaled width of the image * @param height the scaled height of the image * @param observer the observer to notify of image preparation status * @return true if the image is already fully prepared */ public boolean prepareImage(Image image, int width, int height, ImageObserver observer) { // Only heavyweight peers handle this. ComponentPeer p = peer; Component comp = this; while (p instanceof LightweightPeer) { comp = comp.parent; p = comp == null ? null : comp.peer; } boolean retval; if (p != null) retval = p.prepareImage(image, width, height, observer); else retval = getToolkit().prepareImage(image, width, height, observer); return retval; } /** * Returns the status of the loading of the specified image. The value * returned will be those flags defined in <code>ImageObserver</code>. * * @param image the image to check on * @param observer the observer to notify of image loading progress * @return the image observer flags indicating the status of the load * @see #prepareImage(Image, int, int, ImageObserver) * @see Toolkit#checkImage(Image, int, int, ImageObserver) * @throws NullPointerException if image is null */ public int checkImage(Image image, ImageObserver observer) { return checkImage(image, -1, -1, observer); } /** * Returns the status of the loading of the specified image. The value * returned will be those flags defined in <code>ImageObserver</code>. * * @param image the image to check on * @param width the scaled image width * @param height the scaled image height * @param observer the observer to notify of image loading progress * @return the image observer flags indicating the status of the load * @see #prepareImage(Image, int, int, ImageObserver) * @see Toolkit#checkImage(Image, int, int, ImageObserver) */ public int checkImage(Image image, int width, int height, ImageObserver observer) { // Only heavyweight peers handle this. ComponentPeer p = peer; Component comp = this; while (p instanceof LightweightPeer) { comp = comp.parent; p = comp == null ? null : comp.peer; } int retval; if (p != null) retval = p.checkImage(image, width, height, observer); else retval = getToolkit().checkImage(image, width, height, observer); return retval; } /** * Sets whether paint messages delivered by the operating system should be * ignored. This does not affect messages from AWT, except for those * triggered by OS messages. Setting this to true can allow faster * performance in full-screen mode or page-flipping. * * @param ignoreRepaint the new setting for ignoring repaint events * @see #getIgnoreRepaint() * @see BufferStrategy * @see GraphicsDevice#setFullScreenWindow(Window) * @since 1.4 */ public void setIgnoreRepaint(boolean ignoreRepaint) { this.ignoreRepaint = ignoreRepaint; } /** * Test whether paint events from the operating system are ignored. * * @return the status of ignoring paint events * @see #setIgnoreRepaint(boolean) * @since 1.4 */ public boolean getIgnoreRepaint() { return ignoreRepaint; } /** * Tests whether or not the specified point is contained within this * component. Coordinates are relative to this component. * * @param x the X coordinate of the point to test * @param y the Y coordinate of the point to test * @return true if the point is within this component * @see #getComponentAt(int, int) */ public boolean contains(int x, int y) { return inside (x, y); } /** * Tests whether or not the specified point is contained within this * component. Coordinates are relative to this component. * * @param x the X coordinate of the point to test * @param y the Y coordinate of the point to test * @return true if the point is within this component * @deprecated use {@link #contains(int, int)} instead */ public boolean inside(int x, int y) { return x >= 0 && y >= 0 && x < width && y < height; } /** * Tests whether or not the specified point is contained within this * component. Coordinates are relative to this component. * * @param p the point to test * @return true if the point is within this component * @throws NullPointerException if p is null * @see #getComponentAt(Point) * @since 1.1 */ public boolean contains(Point p) { return contains (p.x, p.y); } /** * Returns the component occupying the position (x,y). This will either * be this component, an immediate child component, or <code>null</code> * if neither of the first two occupies the specified location. * * @param x the X coordinate to search for components at * @param y the Y coordinate to search for components at * @return the component at the specified location, or null * @see #contains(int, int) */ public Component getComponentAt(int x, int y) { return locate (x, y); } /** * Returns the component occupying the position (x,y). This will either * be this component, an immediate child component, or <code>null</code> * if neither of the first two occupies the specified location. * * @param x the X coordinate to search for components at * @param y the Y coordinate to search for components at * @return the component at the specified location, or null * @deprecated use {@link #getComponentAt(int, int)} instead */ public Component locate(int x, int y) { return contains (x, y) ? this : null; } /** * Returns the component occupying the position (x,y). This will either * be this component, an immediate child component, or <code>null</code> * if neither of the first two occupies the specified location. * * @param p the point to search for components at * @return the component at the specified location, or null * @throws NullPointerException if p is null * @see #contains(Point) * @since 1.1 */ public Component getComponentAt(Point p) { return getComponentAt (p.x, p.y); } /** * AWT 1.0 event delivery. * * Deliver an AWT 1.0 event to this Component. This method simply * calls {@link #postEvent}. * * @param e the event to deliver * @deprecated use {@link #dispatchEvent (AWTEvent)} instead */ public void deliverEvent (Event e) { postEvent (e); } /** * Forwards AWT events to processEvent() if:<ul> * <li>Events have been enabled for this type of event via * <code>enableEvents()</code></li>, * <li>There is at least one registered listener for this type of event</li> * </ul> * * @param e the event to dispatch */ public final void dispatchEvent(AWTEvent e) { // Some subclasses in the AWT package need to override this behavior, // hence the use of dispatchEventImpl(). dispatchEventImpl(e); } /** * By default, no old mouse events should be ignored. * This can be overridden by subclasses. * * @return false, no mouse events are ignored. */ static boolean ignoreOldMouseEvents() { return false; } /** * AWT 1.0 event handler. * * This method simply calls handleEvent and returns the result. * * @param e the event to handle * @return true if the event was handled, false otherwise * @deprecated use {@link #dispatchEvent(AWTEvent)} instead */ public boolean postEvent (Event e) { boolean handled = handleEvent (e); if (!handled && getParent() != null) // FIXME: need to translate event coordinates to parent's // coordinate space. handled = getParent ().postEvent (e); return handled; } /** * Adds the specified listener to this component. This is harmless if the * listener is null, but if the listener has already been registered, it * will now be registered twice. * * @param listener the new listener to add * @see ComponentEvent * @see #removeComponentListener(ComponentListener) * @see #getComponentListeners() * @since 1.1 */ public synchronized void addComponentListener(ComponentListener listener) { if (listener != null) { componentListener = AWTEventMulticaster.add(componentListener, listener); newEventsOnly = true; } } /** * Removes the specified listener from the component. This is harmless if * the listener was not previously registered. * * @param listener the listener to remove * @see ComponentEvent * @see #addComponentListener(ComponentListener) * @see #getComponentListeners() * @since 1.1 */ public synchronized void removeComponentListener(ComponentListener listener) { componentListener = AWTEventMulticaster.remove(componentListener, listener); } /** * Returns an array of all specified listeners registered on this component. * * @return an array of listeners * @see #addComponentListener(ComponentListener) * @see #removeComponentListener(ComponentListener) * @since 1.4 */ public synchronized ComponentListener[] getComponentListeners() { return (ComponentListener[]) AWTEventMulticaster.getListeners(componentListener, ComponentListener.class); } /** * Adds the specified listener to this component. This is harmless if the * listener is null, but if the listener has already been registered, it * will now be registered twice. * * @param listener the new listener to add * @see FocusEvent * @see #removeFocusListener(FocusListener) * @see #getFocusListeners() * @since 1.1 */ public synchronized void addFocusListener(FocusListener listener) { if (listener != null) { focusListener = AWTEventMulticaster.add(focusListener, listener); newEventsOnly = true; } } /** * Removes the specified listener from the component. This is harmless if * the listener was not previously registered. * * @param listener the listener to remove * @see FocusEvent * @see #addFocusListener(FocusListener) * @see #getFocusListeners() * @since 1.1 */ public synchronized void removeFocusListener(FocusListener listener) { focusListener = AWTEventMulticaster.remove(focusListener, listener); } /** * Returns an array of all specified listeners registered on this component. * * @return an array of listeners * @see #addFocusListener(FocusListener) * @see #removeFocusListener(FocusListener) * @since 1.4 */ public synchronized FocusListener[] getFocusListeners() { return (FocusListener[]) AWTEventMulticaster.getListeners(focusListener, FocusListener.class); } /** * Adds the specified listener to this component. This is harmless if the * listener is null, but if the listener has already been registered, it * will now be registered twice. * * @param listener the new listener to add * @see HierarchyEvent * @see #removeHierarchyListener(HierarchyListener) * @see #getHierarchyListeners() * @since 1.3 */ public synchronized void addHierarchyListener(HierarchyListener listener) { if (listener != null) { hierarchyListener = AWTEventMulticaster.add(hierarchyListener, listener); newEventsOnly = true; // Need to lock the tree, otherwise we might end up inconsistent. synchronized (getTreeLock()) { numHierarchyListeners++; if (parent != null) parent.updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK, 1); } } } /** * Removes the specified listener from the component. This is harmless if * the listener was not previously registered. * * @param listener the listener to remove * @see HierarchyEvent * @see #addHierarchyListener(HierarchyListener) * @see #getHierarchyListeners() * @since 1.3 */ public synchronized void removeHierarchyListener(HierarchyListener listener) { hierarchyListener = AWTEventMulticaster.remove(hierarchyListener, listener); // Need to lock the tree, otherwise we might end up inconsistent. synchronized (getTreeLock()) { numHierarchyListeners--; if (parent != null) parent.updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK, -1); } } /** * Returns an array of all specified listeners registered on this component. * * @return an array of listeners * @see #addHierarchyListener(HierarchyListener) * @see #removeHierarchyListener(HierarchyListener) * @since 1.4 */ public synchronized HierarchyListener[] getHierarchyListeners() { return (HierarchyListener[]) AWTEventMulticaster.getListeners(hierarchyListener, HierarchyListener.class); } /** * Adds the specified listener to this component. This is harmless if the * listener is null, but if the listener has already been registered, it * will now be registered twice. * * @param listener the new listener to add * @see HierarchyEvent * @see #removeHierarchyBoundsListener(HierarchyBoundsListener) * @see #getHierarchyBoundsListeners() * @since 1.3 */ public synchronized void addHierarchyBoundsListener(HierarchyBoundsListener listener) { if (listener != null) { hierarchyBoundsListener = AWTEventMulticaster.add(hierarchyBoundsListener, listener); newEventsOnly = true; // Need to lock the tree, otherwise we might end up inconsistent. synchronized (getTreeLock()) { numHierarchyBoundsListeners++; if (parent != null) parent.updateHierarchyListenerCount (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, 1); } } } /** * Removes the specified listener from the component. This is harmless if * the listener was not previously registered. * * @param listener the listener to remove * @see HierarchyEvent * @see #addHierarchyBoundsListener(HierarchyBoundsListener) * @see #getHierarchyBoundsListeners() * @since 1.3 */ public synchronized void removeHierarchyBoundsListener(HierarchyBoundsListener listener) { hierarchyBoundsListener = AWTEventMulticaster.remove(hierarchyBoundsListener, listener); // Need to lock the tree, otherwise we might end up inconsistent. synchronized (getTreeLock()) { numHierarchyBoundsListeners--; if (parent != null) parent.updateHierarchyListenerCount (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, -1); } } /** * Returns an array of all specified listeners registered on this component. * * @return an array of listeners * @see #addHierarchyBoundsListener(HierarchyBoundsListener) * @see #removeHierarchyBoundsListener(HierarchyBoundsListener) * @since 1.4 */ public synchronized HierarchyBoundsListener[] getHierarchyBoundsListeners() { return (HierarchyBoundsListener[]) AWTEventMulticaster.getListeners(hierarchyBoundsListener, HierarchyBoundsListener.class); } /** * Fires a HierarchyEvent or HierarchyChangeEvent on this component. * * @param id the event id * @param changed the changed component * @param parent the parent * @param flags the event flags */ void fireHierarchyEvent(int id, Component changed, Container parent, long flags) { boolean enabled = false; switch (id) { case HierarchyEvent.HIERARCHY_CHANGED: enabled = hierarchyListener != null || (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0; break; case HierarchyEvent.ANCESTOR_MOVED: case HierarchyEvent.ANCESTOR_RESIZED: enabled = hierarchyBoundsListener != null || (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0; break; default: assert false : "Should not reach here"; } if (enabled) { HierarchyEvent ev = new HierarchyEvent(this, id, changed, parent, flags); dispatchEvent(ev); } } /** * Adds the specified listener to this component. This is harmless if the * listener is null, but if the listener has already been registered, it * will now be registered twice. * * @param listener the new listener to add * @see KeyEvent * @see #removeKeyListener(KeyListener) * @see #getKeyListeners() * @since 1.1 */ public synchronized void addKeyListener(KeyListener listener) { if (listener != null) { keyListener = AWTEventMulticaster.add(keyListener, listener); newEventsOnly = true; } } /** * Removes the specified listener from the component. This is harmless if * the listener was not previously registered. * * @param listener the listener to remove * @see KeyEvent * @see #addKeyListener(KeyListener) * @see #getKeyListeners() * @since 1.1 */ public synchronized void removeKeyListener(KeyListener listener) { keyListener = AWTEventMulticaster.remove(keyListener, listener); } /** * Returns an array of all specified listeners registered on this component. * * @return an array of listeners * @see #addKeyListener(KeyListener) * @see #removeKeyListener(KeyListener) * @since 1.4 */ public synchronized KeyListener[] getKeyListeners() { return (KeyListener[]) AWTEventMulticaster.getListeners(keyListener, KeyListener.class); } /** * Adds the specified listener to this component. This is harmless if the * listener is null, but if the listener has already been registered, it * will now be registered twice. * * @param listener the new listener to add * @see MouseEvent * @see #removeMouseListener(MouseListener) * @see #getMouseListeners() * @since 1.1 */ public synchronized void addMouseListener(MouseListener listener) { if (listener != null) { mouseListener = AWTEventMulticaster.add(mouseListener, listener); newEventsOnly = true; } } /** * Removes the specified listener from the component. This is harmless if * the listener was not previously registered. * * @param listener the listener to remove * @see MouseEvent * @see #addMouseListener(MouseListener) * @see #getMouseListeners() * @since 1.1 */ public synchronized void removeMouseListener(MouseListener listener) { mouseListener = AWTEventMulticaster.remove(mouseListener, listener); } /** * Returns an array of all specified listeners registered on this component. * * @return an array of listeners * @see #addMouseListener(MouseListener) * @see #removeMouseListener(MouseListener) * @since 1.4 */ public synchronized MouseListener[] getMouseListeners() { return (MouseListener[]) AWTEventMulticaster.getListeners(mouseListener, MouseListener.class); } /** * Adds the specified listener to this component. This is harmless if the * listener is null, but if the listener has already been registered, it * will now be registered twice. * * @param listener the new listener to add * @see MouseEvent * @see #removeMouseMotionListener(MouseMotionListener) * @see #getMouseMotionListeners() * @since 1.1 */ public synchronized void addMouseMotionListener(MouseMotionListener listener) { if (listener != null) { mouseMotionListener = AWTEventMulticaster.add(mouseMotionListener, listener); newEventsOnly = true; } } /** * Removes the specified listener from the component. This is harmless if * the listener was not previously registered. * * @param listener the listener to remove * @see MouseEvent * @see #addMouseMotionListener(MouseMotionListener) * @see #getMouseMotionListeners() * @since 1.1 */ public synchronized void removeMouseMotionListener(MouseMotionListener listener) { mouseMotionListener = AWTEventMulticaster.remove(mouseMotionListener, listener); } /** * Returns an array of all specified listeners registered on this component. * * @return an array of listeners * @see #addMouseMotionListener(MouseMotionListener) * @see #removeMouseMotionListener(MouseMotionListener) * @since 1.4 */ public synchronized MouseMotionListener[] getMouseMotionListeners() { return (MouseMotionListener[]) AWTEventMulticaster.getListeners(mouseMotionListener, MouseMotionListener.class); } /** * Adds the specified listener to this component. This is harmless if the * listener is null, but if the listener has already been registered, it * will now be registered twice. * * @param listener the new listener to add * @see MouseEvent * @see MouseWheelEvent * @see #removeMouseWheelListener(MouseWheelListener) * @see #getMouseWheelListeners() * @since 1.4 */ public synchronized void addMouseWheelListener(MouseWheelListener listener) { if (listener != null) { mouseWheelListener = AWTEventMulticaster.add(mouseWheelListener, listener); newEventsOnly = true; } } /** * Removes the specified listener from the component. This is harmless if * the listener was not previously registered. * * @param listener the listener to remove * @see MouseEvent * @see MouseWheelEvent * @see #addMouseWheelListener(MouseWheelListener) * @see #getMouseWheelListeners() * @since 1.4 */ public synchronized void removeMouseWheelListener(MouseWheelListener listener) { mouseWheelListener = AWTEventMulticaster.remove(mouseWheelListener, listener); } /** * Returns an array of all specified listeners registered on this component. * * @return an array of listeners * @see #addMouseWheelListener(MouseWheelListener) * @see #removeMouseWheelListener(MouseWheelListener) * @since 1.4 */ public synchronized MouseWheelListener[] getMouseWheelListeners() { return (MouseWheelListener[]) AWTEventMulticaster.getListeners(mouseWheelListener, MouseWheelListener.class); } /** * Adds the specified listener to this component. This is harmless if the * listener is null, but if the listener has already been registered, it * will now be registered twice. * * @param listener the new listener to add * @see InputMethodEvent * @see #removeInputMethodListener(InputMethodListener) * @see #getInputMethodListeners() * @see #getInputMethodRequests() * @since 1.2 */ public synchronized void addInputMethodListener(InputMethodListener listener) { if (listener != null) { inputMethodListener = AWTEventMulticaster.add(inputMethodListener, listener); newEventsOnly = true; } } /** * Removes the specified listener from the component. This is harmless if * the listener was not previously registered. * * @param listener the listener to remove * @see InputMethodEvent * @see #addInputMethodListener(InputMethodListener) * @see #getInputMethodRequests() * @since 1.2 */ public synchronized void removeInputMethodListener(InputMethodListener listener) { inputMethodListener = AWTEventMulticaster.remove(inputMethodListener, listener); } /** * Returns an array of all specified listeners registered on this component. * * @return an array of listeners * @see #addInputMethodListener(InputMethodListener) * @see #removeInputMethodListener(InputMethodListener) * @since 1.4 */ public synchronized InputMethodListener[] getInputMethodListeners() { return (InputMethodListener[]) AWTEventMulticaster.getListeners(inputMethodListener, InputMethodListener.class); } /** * Returns all registered {@link EventListener}s of the given * <code>listenerType</code>. * * @param listenerType the class of listeners to filter (<code>null</code> * not permitted). * * @return An array of registered listeners. * * @throws ClassCastException if <code>listenerType</code> does not implement * the {@link EventListener} interface. * @throws NullPointerException if <code>listenerType</code> is * <code>null</code>. * * @see #getComponentListeners() * @see #getFocusListeners() * @see #getHierarchyListeners() * @see #getHierarchyBoundsListeners() * @see #getKeyListeners() * @see #getMouseListeners() * @see #getMouseMotionListeners() * @see #getMouseWheelListeners() * @see #getInputMethodListeners() * @see #getPropertyChangeListeners() * @since 1.3 */ public <T extends EventListener> T[] getListeners(Class<T> listenerType) { if (listenerType == ComponentListener.class) return (T[]) getComponentListeners(); if (listenerType == FocusListener.class) return (T[]) getFocusListeners(); if (listenerType == HierarchyListener.class) return (T[]) getHierarchyListeners(); if (listenerType == HierarchyBoundsListener.class) return (T[]) getHierarchyBoundsListeners(); if (listenerType == KeyListener.class) return (T[]) getKeyListeners(); if (listenerType == MouseListener.class) return (T[]) getMouseListeners(); if (listenerType == MouseMotionListener.class) return (T[]) getMouseMotionListeners(); if (listenerType == MouseWheelListener.class) return (T[]) getMouseWheelListeners(); if (listenerType == InputMethodListener.class) return (T[]) getInputMethodListeners(); if (listenerType == PropertyChangeListener.class) return (T[]) getPropertyChangeListeners(); return (T[]) Array.newInstance(listenerType, 0); } /** * Returns the input method request handler, for subclasses which support * on-the-spot text input. By default, input methods are handled by AWT, * and this returns null. * * @return the input method handler, null by default * @since 1.2 */ public InputMethodRequests getInputMethodRequests() { return null; } /** * Gets the input context of this component, which is inherited from the * parent unless this is overridden. * * @return the text input context * @since 1.2 */ public InputContext getInputContext() { return parent == null ? null : parent.getInputContext(); } /** * Enables the specified events. The events to enable are specified * by OR-ing together the desired masks from <code>AWTEvent</code>. * * <p>Events are enabled by default when a listener is attached to the * component for that event type. This method can be used by subclasses * to ensure the delivery of a specified event regardless of whether * or not a listener is attached. * * @param eventsToEnable the desired events to enable * @see #processEvent(AWTEvent) * @see #disableEvents(long) * @see AWTEvent * @since 1.1 */ protected final void enableEvents(long eventsToEnable) { // Update the counter for hierarchy (bounds) listeners. if ((eventsToEnable & AWTEvent.HIERARCHY_EVENT_MASK) != 0 && (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) == 0) { // Need to lock the tree, otherwise we might end up inconsistent. synchronized (getTreeLock()) { numHierarchyListeners++; if (parent != null) parent.updateHierarchyListenerCount (AWTEvent.HIERARCHY_EVENT_MASK, 1); } } if ((eventsToEnable & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0 && (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) == 0) { // Need to lock the tree, otherwise we might end up inconsistent. synchronized (getTreeLock()) { numHierarchyBoundsListeners++; if (parent != null) parent.updateHierarchyListenerCount (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, 1); } } eventMask |= eventsToEnable; newEventsOnly = true; // Only heavyweight peers handle this. ComponentPeer p = peer; Component comp = this; while (p instanceof LightweightPeer) { comp = comp.parent; p = comp == null ? null : comp.peer; } if (p != null) p.setEventMask(eventMask); } /** * Disables the specified events. The events to disable are specified * by OR-ing together the desired masks from <code>AWTEvent</code>. * * @param eventsToDisable the desired events to disable * @see #enableEvents(long) * @since 1.1 */ protected final void disableEvents(long eventsToDisable) { // Update the counter for hierarchy (bounds) listeners. if ((eventsToDisable & AWTEvent.HIERARCHY_EVENT_MASK) != 0 && (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0) { // Need to lock the tree, otherwise we might end up inconsistent. synchronized (getTreeLock()) { numHierarchyListeners--; if (parent != null) parent.updateHierarchyListenerCount (AWTEvent.HIERARCHY_EVENT_MASK, -1); } } if ((eventsToDisable & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0 && (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0) { // Need to lock the tree, otherwise we might end up inconsistent. synchronized (getTreeLock()) { numHierarchyBoundsListeners--; if (parent != null) parent.updateHierarchyListenerCount (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, -1); } } eventMask &= ~eventsToDisable; // Only heavyweight peers handle this. ComponentPeer p = peer; Component comp = this; while (p instanceof LightweightPeer) { comp = comp.parent; p = comp == null ? null : comp.peer; } if (p != null) p.setEventMask(eventMask); } /** * This is called by the EventQueue if two events with the same event id * and owner component are queued. Returns a new combined event, or null if * no combining is done. The coelesced events are currently mouse moves * (intermediate ones are discarded) and paint events (a merged paint is * created in place of the two events). * * @param existingEvent the event on the queue * @param newEvent the new event that might be entered on the queue * @return null if both events are kept, or the replacement coelesced event */ protected AWTEvent coalesceEvents(AWTEvent existingEvent, AWTEvent newEvent) { AWTEvent coalesced = null; switch (existingEvent.id) { case MouseEvent.MOUSE_MOVED: case MouseEvent.MOUSE_DRAGGED: // Just drop the old (intermediate) event and return the new one. MouseEvent me1 = (MouseEvent) existingEvent; MouseEvent me2 = (MouseEvent) newEvent; if (me1.getModifiers() == me2.getModifiers()) coalesced = newEvent; break; case PaintEvent.PAINT: case PaintEvent.UPDATE: // For heavyweights the EventQueue should ask the peer. if (peer == null || peer instanceof LightweightPeer) { PaintEvent pe1 = (PaintEvent) existingEvent; PaintEvent pe2 = (PaintEvent) newEvent; Rectangle r1 = pe1.getUpdateRect(); Rectangle r2 = pe2.getUpdateRect(); if (r1.contains(r2)) coalesced = existingEvent; else if (r2.contains(r1)) coalesced = newEvent; } else { // Replace the event and let the heavyweight figure out the expanding // of the repaint area. coalesced = newEvent; } break; default: coalesced = null; } return coalesced; } /** * Processes the specified event. In this class, this method simply * calls one of the more specific event handlers. * * @param e the event to process * @throws NullPointerException if e is null * @see #processComponentEvent(ComponentEvent) * @see #processFocusEvent(FocusEvent) * @see #processKeyEvent(KeyEvent) * @see #processMouseEvent(MouseEvent) * @see #processMouseMotionEvent(MouseEvent) * @see #processInputMethodEvent(InputMethodEvent) * @see #processHierarchyEvent(HierarchyEvent) * @see #processMouseWheelEvent(MouseWheelEvent) * @since 1.1 */ protected void processEvent(AWTEvent e) { /* Note: the order of these if statements are important. Subclasses must be checked first. Eg. MouseEvent must be checked before ComponentEvent, since a MouseEvent object is also an instance of a ComponentEvent. */ if (e instanceof FocusEvent) processFocusEvent((FocusEvent) e); else if (e instanceof MouseWheelEvent) processMouseWheelEvent((MouseWheelEvent) e); else if (e instanceof MouseEvent) { if (e.id == MouseEvent.MOUSE_MOVED || e.id == MouseEvent.MOUSE_DRAGGED) processMouseMotionEvent((MouseEvent) e); else processMouseEvent((MouseEvent) e); } else if (e instanceof KeyEvent) processKeyEvent((KeyEvent) e); else if (e instanceof InputMethodEvent) processInputMethodEvent((InputMethodEvent) e); else if (e instanceof ComponentEvent) processComponentEvent((ComponentEvent) e); else if (e instanceof HierarchyEvent) { if (e.id == HierarchyEvent.HIERARCHY_CHANGED) processHierarchyEvent((HierarchyEvent) e); else processHierarchyBoundsEvent((HierarchyEvent) e); } } /** * Called when a component event is dispatched and component events are * enabled. This method passes the event along to any listeners * that are attached. * * @param e the <code>ComponentEvent</code> to process * @throws NullPointerException if e is null * @see ComponentListener * @see #addComponentListener(ComponentListener) * @see #enableEvents(long) * @since 1.1 */ protected void processComponentEvent(ComponentEvent e) { if (componentListener == null) return; switch (e.id) { case ComponentEvent.COMPONENT_HIDDEN: componentListener.componentHidden(e); break; case ComponentEvent.COMPONENT_MOVED: componentListener.componentMoved(e); break; case ComponentEvent.COMPONENT_RESIZED: componentListener.componentResized(e); break; case ComponentEvent.COMPONENT_SHOWN: componentListener.componentShown(e); break; } } /** * Called when a focus event is dispatched and component events are * enabled. This method passes the event along to any listeners * that are attached. * * @param e the <code>FocusEvent</code> to process * @throws NullPointerException if e is null * @see FocusListener * @see #addFocusListener(FocusListener) * @see #enableEvents(long) * @since 1.1 */ protected void processFocusEvent(FocusEvent e) { if (focusListener == null) return; switch (e.id) { case FocusEvent.FOCUS_GAINED: focusListener.focusGained(e); break; case FocusEvent.FOCUS_LOST: focusListener.focusLost(e); break; } } /** * Called when a key event is dispatched and component events are * enabled. This method passes the event along to any listeners * that are attached. * * @param e the <code>KeyEvent</code> to process * @throws NullPointerException if e is null * @see KeyListener * @see #addKeyListener(KeyListener) * @see #enableEvents(long) * @since 1.1 */ protected void processKeyEvent(KeyEvent e) { if (keyListener == null) return; switch (e.id) { case KeyEvent.KEY_PRESSED: keyListener.keyPressed(e); break; case KeyEvent.KEY_RELEASED: keyListener.keyReleased(e); break; case KeyEvent.KEY_TYPED: keyListener.keyTyped(e); break; } } /** * Called when a regular mouse event is dispatched and component events are * enabled. This method passes the event along to any listeners * that are attached. * * @param e the <code>MouseEvent</code> to process * @throws NullPointerException if e is null * @see MouseListener * @see #addMouseListener(MouseListener) * @see #enableEvents(long) * @since 1.1 */ protected void processMouseEvent(MouseEvent e) { if (mouseListener == null) return; switch (e.id) { case MouseEvent.MOUSE_CLICKED: mouseListener.mouseClicked(e); break; case MouseEvent.MOUSE_ENTERED: if( isLightweight() ) setCursor( getCursor() ); mouseListener.mouseEntered(e); break; case MouseEvent.MOUSE_EXITED: mouseListener.mouseExited(e); break; case MouseEvent.MOUSE_PRESSED: mouseListener.mousePressed(e); break; case MouseEvent.MOUSE_RELEASED: mouseListener.mouseReleased(e); break; } } /** * Called when a mouse motion event is dispatched and component events are * enabled. This method passes the event along to any listeners * that are attached. * * @param e the <code>MouseMotionEvent</code> to process * @throws NullPointerException if e is null * @see MouseMotionListener * @see #addMouseMotionListener(MouseMotionListener) * @see #enableEvents(long) * @since 1.1 */ protected void processMouseMotionEvent(MouseEvent e) { if (mouseMotionListener == null) return; switch (e.id) { case MouseEvent.MOUSE_DRAGGED: mouseMotionListener.mouseDragged(e); break; case MouseEvent.MOUSE_MOVED: mouseMotionListener.mouseMoved(e); break; } e.consume(); } /** * Called when a mouse wheel event is dispatched and component events are * enabled. This method passes the event along to any listeners that are * attached. * * @param e the <code>MouseWheelEvent</code> to process * @throws NullPointerException if e is null * @see MouseWheelListener * @see #addMouseWheelListener(MouseWheelListener) * @see #enableEvents(long) * @since 1.4 */ protected void processMouseWheelEvent(MouseWheelEvent e) { if (mouseWheelListener != null && e.id == MouseEvent.MOUSE_WHEEL) { mouseWheelListener.mouseWheelMoved(e); e.consume(); } } /** * Called when an input method event is dispatched and component events are * enabled. This method passes the event along to any listeners that are * attached. * * @param e the <code>InputMethodEvent</code> to process * @throws NullPointerException if e is null * @see InputMethodListener * @see #addInputMethodListener(InputMethodListener) * @see #enableEvents(long) * @since 1.2 */ protected void processInputMethodEvent(InputMethodEvent e) { if (inputMethodListener == null) return; switch (e.id) { case InputMethodEvent.CARET_POSITION_CHANGED: inputMethodListener.caretPositionChanged(e); break; case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED: inputMethodListener.inputMethodTextChanged(e); break; } } /** * Called when a hierarchy change event is dispatched and component events * are enabled. This method passes the event along to any listeners that are * attached. * * @param e the <code>HierarchyEvent</code> to process * @throws NullPointerException if e is null * @see HierarchyListener * @see #addHierarchyListener(HierarchyListener) * @see #enableEvents(long) * @since 1.3 */ protected void processHierarchyEvent(HierarchyEvent e) { if (hierarchyListener == null) return; if (e.id == HierarchyEvent.HIERARCHY_CHANGED) hierarchyListener.hierarchyChanged(e); } /** * Called when a hierarchy bounds event is dispatched and component events * are enabled. This method passes the event along to any listeners that are * attached. * * @param e the <code>HierarchyEvent</code> to process * @throws NullPointerException if e is null * @see HierarchyBoundsListener * @see #addHierarchyBoundsListener(HierarchyBoundsListener) * @see #enableEvents(long) * @since 1.3 */ protected void processHierarchyBoundsEvent(HierarchyEvent e) { if (hierarchyBoundsListener == null) return; switch (e.id) { case HierarchyEvent.ANCESTOR_MOVED: hierarchyBoundsListener.ancestorMoved(e); break; case HierarchyEvent.ANCESTOR_RESIZED: hierarchyBoundsListener.ancestorResized(e); break; } } /** * AWT 1.0 event handler. * * This method calls one of the event-specific handler methods. For * example for key events, either {@link #keyDown(Event,int)} * or {@link #keyUp(Event,int)} is called. A derived * component can override one of these event-specific methods if it * only needs to handle certain event types. Otherwise it can * override handleEvent itself and handle any event. * * @param evt the event to handle * @return true if the event was handled, false otherwise * @deprecated use {@link #processEvent(AWTEvent)} instead */ public boolean handleEvent (Event evt) { switch (evt.id) { // Handle key events. case Event.KEY_ACTION: case Event.KEY_PRESS: return keyDown (evt, evt.key); case Event.KEY_ACTION_RELEASE: case Event.KEY_RELEASE: return keyUp (evt, evt.key); // Handle mouse events. case Event.MOUSE_DOWN: return mouseDown (evt, evt.x, evt.y); case Event.MOUSE_UP: return mouseUp (evt, evt.x, evt.y); case Event.MOUSE_MOVE: return mouseMove (evt, evt.x, evt.y); case Event.MOUSE_DRAG: return mouseDrag (evt, evt.x, evt.y); case Event.MOUSE_ENTER: return mouseEnter (evt, evt.x, evt.y); case Event.MOUSE_EXIT: return mouseExit (evt, evt.x, evt.y); // Handle focus events. case Event.GOT_FOCUS: return gotFocus (evt, evt.arg); case Event.LOST_FOCUS: return lostFocus (evt, evt.arg); // Handle action event. case Event.ACTION_EVENT: return action (evt, evt.arg); } // Unknown event. return false; } /** * AWT 1.0 MOUSE_DOWN event handler. This method is meant to be * overridden by components providing their own MOUSE_DOWN handler. * The default implementation simply returns false. * * @param evt the event to handle * @param x the x coordinate, ignored * @param y the y coordinate, ignored * @return false * @deprecated use {@link #processMouseEvent(MouseEvent)} instead */ public boolean mouseDown(Event evt, int x, int y) { return false; } /** * AWT 1.0 MOUSE_DRAG event handler. This method is meant to be * overridden by components providing their own MOUSE_DRAG handler. * The default implementation simply returns false. * * @param evt the event to handle * @param x the x coordinate, ignored * @param y the y coordinate, ignored * @return false * @deprecated use {@link #processMouseMotionEvent(MouseEvent)} instead */ public boolean mouseDrag(Event evt, int x, int y) { return false; } /** * AWT 1.0 MOUSE_UP event handler. This method is meant to be * overridden by components providing their own MOUSE_UP handler. * The default implementation simply returns false. * * @param evt the event to handle * @param x the x coordinate, ignored * @param y the y coordinate, ignored * @return false * @deprecated use {@link #processMouseEvent(MouseEvent)} instead */ public boolean mouseUp(Event evt, int x, int y) { return false; } /** * AWT 1.0 MOUSE_MOVE event handler. This method is meant to be * overridden by components providing their own MOUSE_MOVE handler. * The default implementation simply returns false. * * @param evt the event to handle * @param x the x coordinate, ignored * @param y the y coordinate, ignored * @return false * @deprecated use {@link #processMouseMotionEvent(MouseEvent)} instead */ public boolean mouseMove(Event evt, int x, int y) { return false; } /** * AWT 1.0 MOUSE_ENTER event handler. This method is meant to be * overridden by components providing their own MOUSE_ENTER handler. * The default implementation simply returns false. * * @param evt the event to handle * @param x the x coordinate, ignored * @param y the y coordinate, ignored * @return false * @deprecated use {@link #processMouseEvent(MouseEvent)} instead */ public boolean mouseEnter(Event evt, int x, int y) { return false; } /** * AWT 1.0 MOUSE_EXIT event handler. This method is meant to be * overridden by components providing their own MOUSE_EXIT handler. * The default implementation simply returns false. * * @param evt the event to handle * @param x the x coordinate, ignored * @param y the y coordinate, ignored * @return false * @deprecated use {@link #processMouseEvent(MouseEvent)} instead */ public boolean mouseExit(Event evt, int x, int y) { return false; } /** * AWT 1.0 KEY_PRESS and KEY_ACTION event handler. This method is * meant to be overridden by components providing their own key * press handler. The default implementation simply returns false. * * @param evt the event to handle * @param key the key pressed, ignored * @return false * @deprecated use {@link #processKeyEvent(KeyEvent)} instead */ public boolean keyDown(Event evt, int key) { return false; } /** * AWT 1.0 KEY_RELEASE and KEY_ACTION_RELEASE event handler. This * method is meant to be overridden by components providing their * own key release handler. The default implementation simply * returns false. * * @param evt the event to handle * @param key the key pressed, ignored * @return false * @deprecated use {@link #processKeyEvent(KeyEvent)} instead */ public boolean keyUp(Event evt, int key) { return false; } /** * AWT 1.0 ACTION_EVENT event handler. This method is meant to be * overridden by components providing their own action event * handler. The default implementation simply returns false. * * @param evt the event to handle * @param what the object acted on, ignored * @return false * @deprecated in classes which support actions, use * <code>processActionEvent(ActionEvent)</code> instead */ public boolean action(Event evt, Object what) { return false; } /** * Called when the parent of this Component is made visible or when * the Component is added to an already visible Container and needs * to be shown. A native peer - if any - is created at this * time. This method is called automatically by the AWT system and * should not be called by user level code. * * @see #isDisplayable() * @see #removeNotify() */ public void addNotify() { // We need to lock the tree here to avoid races and inconsistencies. synchronized (getTreeLock()) { if (peer == null) peer = getToolkit().createComponent(this); else if (parent != null && parent.isLightweight()) new HeavyweightInLightweightListener(parent); // Now that all the children has gotten their peers, we should // have the event mask needed for this component and its //lightweight subcomponents. peer.setEventMask(eventMask); // We used to leave the invalidate() to the peer. However, I put it // back here for 2 reasons: 1) The RI does call invalidate() from // addNotify(); 2) The peer shouldn't be bother with validation too // much. invalidate(); if (dropTarget != null) dropTarget.addNotify(peer); // Fetch the peerFont for later installation in validate(). peerFont = getFont(); // Notify hierarchy listeners. long flags = HierarchyEvent.DISPLAYABILITY_CHANGED; if (isHierarchyVisible()) flags |= HierarchyEvent.SHOWING_CHANGED; fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, this, parent, flags); } } /** * Called to inform this component is has been removed from its * container. Its native peer - if any - is destroyed at this time. * This method is called automatically by the AWT system and should * not be called by user level code. * * @see #isDisplayable() * @see #addNotify() */ public void removeNotify() { // We need to lock the tree here to avoid races and inconsistencies. synchronized (getTreeLock()) { // We null our peer field before disposing of it, such that if we're // not the event dispatch thread and the dispatch thread is awoken by // the dispose call, there will be no race checking the peer's null // status. ComponentPeer tmp = peer; peer = null; peerFont = null; if (tmp != null) { tmp.hide(); tmp.dispose(); } // Notify hierarchy listeners. long flags = HierarchyEvent.DISPLAYABILITY_CHANGED; if (isHierarchyVisible()) flags |= HierarchyEvent.SHOWING_CHANGED; fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, this, parent, flags); } } /** * AWT 1.0 GOT_FOCUS event handler. This method is meant to be * overridden by components providing their own GOT_FOCUS handler. * The default implementation simply returns false. * * @param evt the event to handle * @param what the Object focused, ignored * @return false * @deprecated use {@link #processFocusEvent(FocusEvent)} instead */ public boolean gotFocus(Event evt, Object what) { return false; } /** * AWT 1.0 LOST_FOCUS event handler. This method is meant to be * overridden by components providing their own LOST_FOCUS handler. * The default implementation simply returns false. * * @param evt the event to handle * @param what the Object focused, ignored * @return false * @deprecated use {@link #processFocusEvent(FocusEvent)} instead */ public boolean lostFocus(Event evt, Object what) { return false; } /** * Tests whether or not this component is in the group that can be * traversed using the keyboard traversal mechanism (such as the TAB key). * * @return true if the component is traversed via the TAB key * @see #setFocusable(boolean) * @since 1.1 * @deprecated use {@link #isFocusable()} instead */ public boolean isFocusTraversable() { return enabled && visible && (peer == null || isLightweight() || peer.isFocusTraversable()); } /** * Tests if this component can receive focus. * * @return true if this component can receive focus * @since 1.4 */ public boolean isFocusable() { return focusable; } /** * Specify whether this component can receive focus. This method also * sets the {@link #isFocusTraversableOverridden} field to 1, which * appears to be the undocumented way {@link * DefaultFocusTraversalPolicy#accept(Component)} determines whether to * respect the {@link #isFocusable()} method of the component. * * @param focusable the new focusable status * @since 1.4 */ public void setFocusable(boolean focusable) { firePropertyChange("focusable", this.focusable, focusable); this.focusable = focusable; this.isFocusTraversableOverridden = 1; } /** * Sets the focus traversal keys for one of the three focus * traversal directions supported by Components: * {@link KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS}, * {@link KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS}, or * {@link KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS}. Normally, the * default values should match the operating system's native * choices. To disable a given traversal, use * <code>Collections.EMPTY_SET</code>. The event dispatcher will * consume PRESSED, RELEASED, and TYPED events for the specified * key, although focus can only transfer on PRESSED or RELEASED. * * <p>The defaults are: * <table> * <th><td>Identifier</td><td>Meaning</td><td>Default</td></th> * <tr><td>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</td> * <td>Normal forward traversal</td> * <td>TAB on KEY_PRESSED, Ctrl-TAB on KEY_PRESSED</td></tr> * <tr><td>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</td> * <td>Normal backward traversal</td> * <td>Shift-TAB on KEY_PRESSED, Ctrl-Shift-TAB on KEY_PRESSED</td></tr> * <tr><td>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</td> * <td>Go up a traversal cycle</td><td>None</td></tr> * </table> * * If keystrokes is null, this component's focus traversal key set * is inherited from one of its ancestors. If none of its ancestors * has its own set of focus traversal keys, the focus traversal keys * are set to the defaults retrieved from the current * KeyboardFocusManager. If not null, the set must contain only * AWTKeyStrokes that are not already focus keys and are not * KEY_TYPED events. * * @param id one of FORWARD_TRAVERSAL_KEYS, BACKWARD_TRAVERSAL_KEYS, or * UP_CYCLE_TRAVERSAL_KEYS * @param keystrokes a set of keys, or null * @throws IllegalArgumentException if id or keystrokes is invalid * @see #getFocusTraversalKeys(int) * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS * @since 1.4 */ public void setFocusTraversalKeys(int id, Set<? extends AWTKeyStroke> keystrokes) { if (keystrokes == null) { Container parent = getParent (); while (parent != null) { if (parent.areFocusTraversalKeysSet (id)) { keystrokes = parent.getFocusTraversalKeys (id); break; } parent = parent.getParent (); } if (keystrokes == null) keystrokes = KeyboardFocusManager.getCurrentKeyboardFocusManager (). getDefaultFocusTraversalKeys (id); } Set sa; Set sb; String name; switch (id) { case KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS: sa = getFocusTraversalKeys (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); sb = getFocusTraversalKeys (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS); name = "forwardFocusTraversalKeys"; break; case KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS: sa = getFocusTraversalKeys (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); sb = getFocusTraversalKeys (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS); name = "backwardFocusTraversalKeys"; break; case KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS: sa = getFocusTraversalKeys (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); sb = getFocusTraversalKeys (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); name = "upCycleFocusTraversalKeys"; break; default: throw new IllegalArgumentException (); } int i = keystrokes.size (); Iterator iter = keystrokes.iterator (); while (--i >= 0) { Object o = iter.next (); if (!(o instanceof AWTKeyStroke) || sa.contains (o) || sb.contains (o) || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED) throw new IllegalArgumentException (); } if (focusTraversalKeys == null) focusTraversalKeys = new Set[3]; keystrokes = Collections.unmodifiableSet (new HashSet (keystrokes)); firePropertyChange (name, focusTraversalKeys[id], keystrokes); focusTraversalKeys[id] = keystrokes; } /** * Returns the set of keys for a given focus traversal action, as * defined in <code>setFocusTraversalKeys</code>. If not set, this * is inherited from the parent component, which may have gotten it * from the KeyboardFocusManager. * * @param id one of FORWARD_TRAVERSAL_KEYS, BACKWARD_TRAVERSAL_KEYS, * or UP_CYCLE_TRAVERSAL_KEYS * * @return set of traversal keys * * @throws IllegalArgumentException if id is invalid * * @see #setFocusTraversalKeys (int, Set) * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS * * @since 1.4 */ public Set<AWTKeyStroke> getFocusTraversalKeys (int id) { if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS && id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS && id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS) throw new IllegalArgumentException(); Set<AWTKeyStroke> s = null; if (focusTraversalKeys != null) s = focusTraversalKeys[id]; if (s == null && parent != null) s = parent.getFocusTraversalKeys (id); return s == null ? (KeyboardFocusManager.getCurrentKeyboardFocusManager() .getDefaultFocusTraversalKeys(id)) : s; } /** * Tests whether the focus traversal keys for a given action are explicitly * set or inherited. * * @param id one of FORWARD_TRAVERSAL_KEYS, BACKWARD_TRAVERSAL_KEYS, * or UP_CYCLE_TRAVERSAL_KEYS * @return true if that set is explicitly specified * @throws IllegalArgumentException if id is invalid * @see #getFocusTraversalKeys (int) * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS * @since 1.4 */ public boolean areFocusTraversalKeysSet (int id) { if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS && id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS && id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS) throw new IllegalArgumentException (); return focusTraversalKeys != null && focusTraversalKeys[id] != null; } /** * Enable or disable focus traversal keys on this Component. If * they are, then the keyboard focus manager consumes and acts on * key press and release events that trigger focus traversal, and * discards the corresponding key typed events. If focus traversal * keys are disabled, then all key events that would otherwise * trigger focus traversal are sent to this Component. * * @param focusTraversalKeysEnabled the new value of the flag * @see #getFocusTraversalKeysEnabled () * @see #setFocusTraversalKeys (int, Set) * @see #getFocusTraversalKeys (int) * @since 1.4 */ public void setFocusTraversalKeysEnabled (boolean focusTraversalKeysEnabled) { firePropertyChange ("focusTraversalKeysEnabled", this.focusTraversalKeysEnabled, focusTraversalKeysEnabled); this.focusTraversalKeysEnabled = focusTraversalKeysEnabled; } /** * Check whether or not focus traversal keys are enabled on this * Component. If they are, then the keyboard focus manager consumes * and acts on key press and release events that trigger focus * traversal, and discards the corresponding key typed events. If * focus traversal keys are disabled, then all key events that would * otherwise trigger focus traversal are sent to this Component. * * @return true if focus traversal keys are enabled * @see #setFocusTraversalKeysEnabled (boolean) * @see #setFocusTraversalKeys (int, Set) * @see #getFocusTraversalKeys (int) * @since 1.4 */ public boolean getFocusTraversalKeysEnabled () { return focusTraversalKeysEnabled; } /** * Request that this Component be given the keyboard input focus and * that its top-level ancestor become the focused Window. * * For the request to be granted, the Component must be focusable, * displayable and showing and the top-level Window to which it * belongs must be focusable. If the request is initially denied on * the basis that the top-level Window is not focusable, the request * will be remembered and granted when the Window does become * focused. * * Never assume that this Component is the focus owner until it * receives a FOCUS_GAINED event. * * The behaviour of this method is platform-dependent. * {@link #requestFocusInWindow()} should be used instead. * * @see #requestFocusInWindow () * @see FocusEvent * @see #addFocusListener (FocusListener) * @see #isFocusable () * @see #isDisplayable () * @see KeyboardFocusManager#clearGlobalFocusOwner () */ public void requestFocus () { requestFocusImpl(false, true); } /** * Request that this Component be given the keyboard input focus and * that its top-level ancestor become the focused Window. * * For the request to be granted, the Component must be focusable, * displayable and showing and the top-level Window to which it * belongs must be focusable. If the request is initially denied on * the basis that the top-level Window is not focusable, the request * will be remembered and granted when the Window does become * focused. * * Never assume that this Component is the focus owner until it * receives a FOCUS_GAINED event. * * The behaviour of this method is platform-dependent. * {@link #requestFocusInWindow()} should be used instead. * * If the return value is false, the request is guaranteed to fail. * If the return value is true, the request will succeed unless it * is vetoed or something in the native windowing system intervenes, * preventing this Component's top-level ancestor from becoming * focused. This method is meant to be called by derived * lightweight Components that want to avoid unnecessary repainting * when they know a given focus transfer need only be temporary. * * @param temporary true if the focus request is temporary * @return true if the request has a chance of success * @see #requestFocusInWindow () * @see FocusEvent * @see #addFocusListener (FocusListener) * @see #isFocusable () * @see #isDisplayable () * @see KeyboardFocusManager#clearGlobalFocusOwner () * @since 1.4 */ protected boolean requestFocus (boolean temporary) { return requestFocusImpl(temporary, true); } /** * Request that this component be given the keyboard input focus, if * its top-level ancestor is the currently focused Window. A * <code>FOCUS_GAINED</code> event will be fired if and only if this * request is successful. To be successful, the component must be * displayable, showing, and focusable, and its ancestor top-level * Window must be focused. * * If the return value is false, the request is guaranteed to fail. * If the return value is true, the request will succeed unless it * is vetoed or something in the native windowing system intervenes, * preventing this Component's top-level ancestor from becoming * focused. * * @return true if the request has a chance of success * @see #requestFocus () * @see FocusEvent * @see #addFocusListener (FocusListener) * @see #isFocusable () * @see #isDisplayable () * @see KeyboardFocusManager#clearGlobalFocusOwner () * @since 1.4 */ public boolean requestFocusInWindow () { return requestFocusImpl(false, false); } /** * Request that this component be given the keyboard input focus, if * its top-level ancestor is the currently focused Window. A * <code>FOCUS_GAINED</code> event will be fired if and only if this * request is successful. To be successful, the component must be * displayable, showing, and focusable, and its ancestor top-level * Window must be focused. * * If the return value is false, the request is guaranteed to fail. * If the return value is true, the request will succeed unless it * is vetoed or something in the native windowing system intervenes, * preventing this Component's top-level ancestor from becoming * focused. This method is meant to be called by derived * lightweight Components that want to avoid unnecessary repainting * when they know a given focus transfer need only be temporary. * * @param temporary true if the focus request is temporary * @return true if the request has a chance of success * @see #requestFocus () * @see FocusEvent * @see #addFocusListener (FocusListener) * @see #isFocusable () * @see #isDisplayable () * @see KeyboardFocusManager#clearGlobalFocusOwner () * @since 1.4 */ protected boolean requestFocusInWindow (boolean temporary) { return requestFocusImpl(temporary, false); } /** * Helper method for all 4 requestFocus variants. * * @param temporary indicates if the focus change is temporary * @param focusWindow indicates if the window focus may be changed * * @return <code>false</code> if the request has been definitely denied, * <code>true</code> otherwise */ private boolean requestFocusImpl(boolean temporary, boolean focusWindow) { boolean retval = false; // Don't try to focus non-focusable and non-visible components. if (isFocusable() && isVisible()) { ComponentPeer myPeer = peer; if (peer != null) { // Find Window ancestor and find out if we're showing while // doing this. boolean showing = true; Component window = this; while (! (window instanceof Window)) { if (! window.isVisible()) showing = false; window = window.parent; } // Don't allow focus when there is no window or the window // is not focusable. if (window != null && ((Window) window).isFocusableWindow() && showing) { // Search for nearest heavy ancestor (including this // component). Component heavyweightParent = this; while (heavyweightParent.peer instanceof LightweightPeer) heavyweightParent = heavyweightParent.parent; // Don't allow focus on lightweight components without // visible heavyweight ancestor if (heavyweightParent != null && heavyweightParent.isVisible()) { // Don't allow focus when heavyweightParent has no peer. myPeer = heavyweightParent.peer; if (myPeer != null) { // Register lightweight focus request. if (heavyweightParent != this) { KeyboardFocusManager .addLightweightFocusRequest(heavyweightParent, this); } // Try to focus the component. long time = EventQueue.getMostRecentEventTime(); boolean success = myPeer.requestFocus(this, temporary, focusWindow, time); if (! success) { // Dequeue key events if focus request failed. KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); kfm.dequeueKeyEvents(time, this); } retval = success; } } } } } return retval; } /** * Transfers focus to the next component in the focus traversal * order, as though this were the current focus owner. * * @see #requestFocus() * @since 1.1 */ public void transferFocus () { nextFocus (); } /** * Returns the root container that owns the focus cycle where this * component resides. A focus cycle root is in two cycles, one as * the ancestor, and one as the focusable element; this call always * returns the ancestor. * * @return the ancestor container that owns the focus cycle * @since 1.4 */ public Container getFocusCycleRootAncestor () { Container parent = getParent (); while (parent != null && !parent.isFocusCycleRoot()) parent = parent.getParent (); return parent; } /** * Tests if the container is the ancestor of the focus cycle that * this component belongs to. * * @param c the container to test * @return true if c is the focus cycle root * @since 1.4 */ public boolean isFocusCycleRoot (Container c) { return c == getFocusCycleRootAncestor (); } /** * AWT 1.0 focus event processor. Transfers focus to the next * component in the focus traversal order, as though this were the * current focus owner. * * @deprecated use {@link #transferFocus ()} instead */ public void nextFocus () { // Find the nearest valid (== showing && focusable && enabled) focus // cycle root ancestor and the focused component in it. Container focusRoot = getFocusCycleRootAncestor(); Component focusComp = this; while (focusRoot != null && ! (focusRoot.isShowing() && focusRoot.isFocusable() && focusRoot.isEnabled())) { focusComp = focusRoot; focusRoot = focusComp.getFocusCycleRootAncestor(); } if (focusRoot != null) { // First try to get the componentBefore from the policy. FocusTraversalPolicy policy = focusRoot.getFocusTraversalPolicy(); Component nextFocus = policy.getComponentAfter(focusRoot, focusComp); // If this fails, then ask for the defaultComponent. if (nextFocus == null) nextFocus = policy.getDefaultComponent(focusRoot); // Request focus on this component, if not null. if (nextFocus != null) nextFocus.requestFocus(); } } /** * Transfers focus to the previous component in the focus traversal * order, as though this were the current focus owner. * * @see #requestFocus () * @since 1.4 */ public void transferFocusBackward () { // Find the nearest valid (== showing && focusable && enabled) focus // cycle root ancestor and the focused component in it. Container focusRoot = getFocusCycleRootAncestor(); Component focusComp = this; while (focusRoot != null && ! (focusRoot.isShowing() && focusRoot.isFocusable() && focusRoot.isEnabled())) { focusComp = focusRoot; focusRoot = focusComp.getFocusCycleRootAncestor(); } if (focusRoot != null) { // First try to get the componentBefore from the policy. FocusTraversalPolicy policy = focusRoot.getFocusTraversalPolicy(); Component nextFocus = policy.getComponentBefore(focusRoot, focusComp); // If this fails, then ask for the defaultComponent. if (nextFocus == null) nextFocus = policy.getDefaultComponent(focusRoot); // Request focus on this component, if not null. if (nextFocus != null) nextFocus.requestFocus(); } } /** * Transfers focus to the focus cycle root of this component. * However, if this is a Window, the default focus owner in the * window in the current focus cycle is focused instead. * * @see #requestFocus() * @see #isFocusCycleRoot(Container) * @since 1.4 */ public void transferFocusUpCycle () { // Find the nearest focus cycle root ancestor that is itself // focusable, showing and enabled. Container focusCycleRoot = getFocusCycleRootAncestor(); while (focusCycleRoot != null && ! (focusCycleRoot.isShowing() && focusCycleRoot.isFocusable() && focusCycleRoot.isEnabled())) { focusCycleRoot = focusCycleRoot.getFocusCycleRootAncestor(); } KeyboardFocusManager fm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); if (focusCycleRoot != null) { // If we found a focus cycle root, then we make this the new // focused component, and make it's focus cycle root the new // global focus cycle root. If the found root has no focus cycle // root ancestor itself, then the component will be both the focused // component and the new global focus cycle root. Container focusCycleAncestor = focusCycleRoot.getFocusCycleRootAncestor(); Container globalFocusCycleRoot; if (focusCycleAncestor == null) globalFocusCycleRoot = focusCycleRoot; else globalFocusCycleRoot = focusCycleAncestor; fm.setGlobalCurrentFocusCycleRoot(globalFocusCycleRoot); focusCycleRoot.requestFocus(); } else { // If this component has no applicable focus cycle root, we try // find the nearest window and set this as the new global focus cycle // root and the default focus component of this window the new focused // component. Container cont; if (this instanceof Container) cont = (Container) this; else cont = getParent(); while (cont != null && !(cont instanceof Window)) cont = cont.getParent(); if (cont != null) { FocusTraversalPolicy policy = cont.getFocusTraversalPolicy(); Component focusComp = policy.getDefaultComponent(cont); if (focusComp != null) { fm.setGlobalCurrentFocusCycleRoot(cont); focusComp.requestFocus(); } } } } /** * Tests if this component is the focus owner. Use {@link * #isFocusOwner ()} instead. * * @return true if this component owns focus * @since 1.2 */ public boolean hasFocus () { KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager (); Component focusOwner = manager.getFocusOwner (); return this == focusOwner; } /** * Tests if this component is the focus owner. * * @return true if this component owns focus * @since 1.4 */ public boolean isFocusOwner() { return hasFocus (); } /** * Adds the specified popup menu to this component. * * @param popup the popup menu to be added * * @see #remove(MenuComponent) * * @since 1.1 */ public synchronized void add(PopupMenu popup) { if (popups == null) popups = new Vector(); popups.add(popup); if (popup.parent != null) popup.parent.remove(popup); popup.parent = this; if (peer != null) popup.addNotify(); } /** * Removes the specified popup menu from this component. * * @param popup the popup menu to remove * @see #add(PopupMenu) * @since 1.1 */ public synchronized void remove(MenuComponent popup) { if (popups != null) popups.remove(popup); } /** * Returns a debugging string representing this component. The string may * be empty but not null. * * @return a string representing this component */ protected String paramString() { CPStringBuilder param = new CPStringBuilder(); String name = getName(); if (name != null) param.append(name).append(","); param.append(x).append(",").append(y).append(",").append(width) .append("x").append(height); if (! isValid()) param.append(",invalid"); if (! isVisible()) param.append(",invisible"); if (! isEnabled()) param.append(",disabled"); if (! isOpaque()) param.append(",translucent"); if (isDoubleBuffered()) param.append(",doublebuffered"); if (parent == null) param.append(",parent=null"); else param.append(",parent=").append(parent.getName()); return param.toString(); } /** * Returns a string representation of this component. This is implemented * as <code>getClass().getName() + '[' + paramString() + ']'</code>. * * @return a string representation of this component */ public String toString() { return getClass().getName() + '[' + paramString() + ']'; } /** * Prints a listing of this component to <code>System.out</code>. * * @see #list(PrintStream) */ public void list() { list(System.out, 0); } /** * Prints a listing of this component to the specified print stream. * * @param out the <code>PrintStream</code> to print to */ public void list(PrintStream out) { list(out, 0); } /** * Prints a listing of this component to the specified print stream, * starting at the specified indentation point. * * @param out the <code>PrintStream</code> to print to * @param indent the indentation point */ public void list(PrintStream out, int indent) { for (int i = 0; i < indent; ++i) out.print(' '); out.println(toString()); } /** * Prints a listing of this component to the specified print writer. * * @param out the <code>PrintWrinter</code> to print to * @since 1.1 */ public void list(PrintWriter out) { list(out, 0); } /** * Prints a listing of this component to the specified print writer, * starting at the specified indentation point. * * @param out the <code>PrintWriter</code> to print to * @param indent the indentation point * @since 1.1 */ public void list(PrintWriter out, int indent) { for (int i = 0; i < indent; ++i) out.print(' '); out.println(toString()); } /** * Adds the specified property listener to this component. This is harmless * if the listener is null, but if the listener has already been registered, * it will now be registered twice. The property listener ignores inherited * properties. Recognized properties include:<br> * <ul> * <li>the font (<code>"font"</code>)</li> * <li>the background color (<code>"background"</code>)</li> * <li>the foreground color (<code>"foreground"</code>)</li> * <li>the focusability (<code>"focusable"</code>)</li> * <li>the focus key traversal enabled state * (<code>"focusTraversalKeysEnabled"</code>)</li> * <li>the set of forward traversal keys * (<code>"forwardFocusTraversalKeys"</code>)</li> * <li>the set of backward traversal keys * (<code>"backwardFocusTraversalKeys"</code>)</li> * <li>the set of up-cycle traversal keys * (<code>"upCycleFocusTraversalKeys"</code>)</li> * </ul> * * @param listener the new listener to add * @see #removePropertyChangeListener(PropertyChangeListener) * @see #getPropertyChangeListeners() * @see #addPropertyChangeListener(String, PropertyChangeListener) * @since 1.1 */ public void addPropertyChangeListener(PropertyChangeListener listener) { if (changeSupport == null) changeSupport = new PropertyChangeSupport(this); changeSupport.addPropertyChangeListener(listener); } /** * Removes the specified property listener from the component. This is * harmless if the listener was not previously registered. * * @param listener the listener to remove * @see #addPropertyChangeListener(PropertyChangeListener) * @see #getPropertyChangeListeners() * @see #removePropertyChangeListener(String, PropertyChangeListener) * @since 1.1 */ public void removePropertyChangeListener(PropertyChangeListener listener) { if (changeSupport != null) changeSupport.removePropertyChangeListener(listener); } /** * Returns an array of all specified listeners registered on this component. * * @return an array of listeners * @see #addPropertyChangeListener(PropertyChangeListener) * @see #removePropertyChangeListener(PropertyChangeListener) * @see #getPropertyChangeListeners(String) * @since 1.4 */ public PropertyChangeListener[] getPropertyChangeListeners() { return changeSupport == null ? new PropertyChangeListener[0] : changeSupport.getPropertyChangeListeners(); } /** * Adds the specified property listener to this component. This is harmless * if the listener is null, but if the listener has already been registered, * it will now be registered twice. The property listener ignores inherited * properties. The listener is keyed to a single property. Recognized * properties include:<br> * <ul> * <li>the font (<code>"font"</code>)</li> * <li>the background color (<code>"background"</code>)</li> * <li>the foreground color (<code>"foreground"</code>)</li> * <li>the focusability (<code>"focusable"</code>)</li> * <li>the focus key traversal enabled state * (<code>"focusTraversalKeysEnabled"</code>)</li> * <li>the set of forward traversal keys * (<code>"forwardFocusTraversalKeys"</code>)</li> p * <li>the set of backward traversal keys * (<code>"backwardFocusTraversalKeys"</code>)</li> * <li>the set of up-cycle traversal keys * (<code>"upCycleFocusTraversalKeys"</code>)</li> * </ul> * * @param propertyName the property name to filter on * @param listener the new listener to add * @see #removePropertyChangeListener(String, PropertyChangeListener) * @see #getPropertyChangeListeners(String) * @see #addPropertyChangeListener(PropertyChangeListener) * @since 1.1 */ public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { if (changeSupport == null) changeSupport = new PropertyChangeSupport(this); changeSupport.addPropertyChangeListener(propertyName, listener); } /** * Removes the specified property listener on a particular property from * the component. This is harmless if the listener was not previously * registered. * * @param propertyName the property name to filter on * @param listener the listener to remove * @see #addPropertyChangeListener(String, PropertyChangeListener) * @see #getPropertyChangeListeners(String) * @see #removePropertyChangeListener(PropertyChangeListener) * @since 1.1 */ public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { if (changeSupport != null) changeSupport.removePropertyChangeListener(propertyName, listener); } /** * Returns an array of all specified listeners on the named property that * are registered on this component. * * @return an array of listeners * @see #addPropertyChangeListener(String, PropertyChangeListener) * @see #removePropertyChangeListener(String, PropertyChangeListener) * @see #getPropertyChangeListeners() * @since 1.4 */ public PropertyChangeListener[] getPropertyChangeListeners(String property) { return changeSupport == null ? new PropertyChangeListener[0] : changeSupport.getPropertyChangeListeners(property); } /** * Report a change in a bound property to any registered property listeners. * * @param propertyName the property that changed * @param oldValue the old property value * @param newValue the new property value */ protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { if (changeSupport != null) changeSupport.firePropertyChange(propertyName, oldValue, newValue); } /** * Report a change in a bound property to any registered property listeners. * * @param propertyName the property that changed * @param oldValue the old property value * @param newValue the new property value */ protected void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) { if (changeSupport != null) changeSupport.firePropertyChange(propertyName, oldValue, newValue); } /** * Report a change in a bound property to any registered property listeners. * * @param propertyName the property that changed * @param oldValue the old property value * @param newValue the new property value */ protected void firePropertyChange(String propertyName, int oldValue, int newValue) { if (changeSupport != null) changeSupport.firePropertyChange(propertyName, oldValue, newValue); } /** * Report a change in a bound property to any registered property listeners. * * @param propertyName the property that changed * @param oldValue the old property value * @param newValue the new property value * * @since 1.5 */ public void firePropertyChange(String propertyName, byte oldValue, byte newValue) { if (changeSupport != null) changeSupport.firePropertyChange(propertyName, new Byte(oldValue), new Byte(newValue)); } /** * Report a change in a bound property to any registered property listeners. * * @param propertyName the property that changed * @param oldValue the old property value * @param newValue the new property value * * @since 1.5 */ public void firePropertyChange(String propertyName, char oldValue, char newValue) { if (changeSupport != null) changeSupport.firePropertyChange(propertyName, new Character(oldValue), new Character(newValue)); } /** * Report a change in a bound property to any registered property listeners. * * @param propertyName the property that changed * @param oldValue the old property value * @param newValue the new property value * * @since 1.5 */ public void firePropertyChange(String propertyName, short oldValue, short newValue) { if (changeSupport != null) changeSupport.firePropertyChange(propertyName, new Short(oldValue), new Short(newValue)); } /** * Report a change in a bound property to any registered property listeners. * * @param propertyName the property that changed * @param oldValue the old property value * @param newValue the new property value * * @since 1.5 */ public void firePropertyChange(String propertyName, long oldValue, long newValue) { if (changeSupport != null) changeSupport.firePropertyChange(propertyName, new Long(oldValue), new Long(newValue)); } /** * Report a change in a bound property to any registered property listeners. * * @param propertyName the property that changed * @param oldValue the old property value * @param newValue the new property value * * @since 1.5 */ public void firePropertyChange(String propertyName, float oldValue, float newValue) { if (changeSupport != null) changeSupport.firePropertyChange(propertyName, new Float(oldValue), new Float(newValue)); } /** * Report a change in a bound property to any registered property listeners. * * @param propertyName the property that changed * @param oldValue the old property value * @param newValue the new property value * * @since 1.5 */ public void firePropertyChange(String propertyName, double oldValue, double newValue) { if (changeSupport != null) changeSupport.firePropertyChange(propertyName, new Double(oldValue), new Double(newValue)); } /** * Sets the text layout orientation of this component. New components default * to UNKNOWN (which behaves like LEFT_TO_RIGHT). This method affects only * the current component, while * {@link #applyComponentOrientation(ComponentOrientation)} affects the * entire hierarchy. * * @param o the new orientation (<code>null</code> is accepted) * @see #getComponentOrientation() */ public void setComponentOrientation(ComponentOrientation o) { ComponentOrientation oldOrientation = componentOrientation; componentOrientation = o; firePropertyChange("componentOrientation", oldOrientation, o); } /** * Determines the text layout orientation used by this component. * * @return the component orientation (this can be <code>null</code>) * @see #setComponentOrientation(ComponentOrientation) */ public ComponentOrientation getComponentOrientation() { return componentOrientation; } /** * Sets the text layout orientation of this component. New components default * to UNKNOWN (which behaves like LEFT_TO_RIGHT). This method affects the * entire hierarchy, while * {@link #setComponentOrientation(ComponentOrientation)} affects only the * current component. * * @param o the new orientation * @throws NullPointerException if o is null * @see #getComponentOrientation() * @since 1.4 */ public void applyComponentOrientation(ComponentOrientation o) { setComponentOrientation(o); } /** * Returns the accessibility framework context of this class. Component is * not accessible, so the default implementation returns null. Subclasses * must override this behavior, and return an appropriate subclass of * {@link AccessibleAWTComponent}. * * @return the accessibility context */ public AccessibleContext getAccessibleContext() { return null; } // Helper methods; some are package visible for use by subclasses. /** * Subclasses should override this to return unique component names like * "menuitem0". * * @return the generated name for this component */ String generateName() { // Component is abstract. return null; } /** * Sets the peer for this component. * * @param peer the new peer */ final void setPeer(ComponentPeer peer) { this.peer = peer; } /** * Translate an AWT 1.1 event ({@link AWTEvent}) into an AWT 1.0 * event ({@link Event}). * * @param e an AWT 1.1 event to translate * * @return an AWT 1.0 event representing e */ static Event translateEvent (AWTEvent e) { Object target = e.getSource (); Event translated = null; if (e instanceof WindowEvent) { WindowEvent we = (WindowEvent) e; int id = we.id; int newId = 0; switch (id) { case WindowEvent.WINDOW_DEICONIFIED: newId = Event.WINDOW_DEICONIFY; break; case WindowEvent.WINDOW_CLOSED: case WindowEvent.WINDOW_CLOSING: newId = Event.WINDOW_DESTROY; break; case WindowEvent.WINDOW_ICONIFIED: newId = Event.WINDOW_ICONIFY; break; case WindowEvent.WINDOW_GAINED_FOCUS: newId = Event.GOT_FOCUS; break; case WindowEvent.WINDOW_LOST_FOCUS: newId = Event.LOST_FOCUS; break; default: return null; } translated = new Event(target, 0, newId, 0, 0, 0, 0); } else if (e instanceof InputEvent) { InputEvent ie = (InputEvent) e; long when = ie.getWhen (); int oldID = 0; int id = e.getID (); int oldMods = 0; int mods = ie.getModifiersEx (); if ((mods & InputEvent.BUTTON2_DOWN_MASK) != 0) oldMods |= Event.META_MASK; else if ((mods & InputEvent.BUTTON3_DOWN_MASK) != 0) oldMods |= Event.ALT_MASK; if ((mods & InputEvent.SHIFT_DOWN_MASK) != 0) oldMods |= Event.SHIFT_MASK; if ((mods & InputEvent.CTRL_DOWN_MASK) != 0) oldMods |= Event.CTRL_MASK; if ((mods & InputEvent.META_DOWN_MASK) != 0) oldMods |= Event.META_MASK; if ((mods & InputEvent.ALT_DOWN_MASK) != 0) oldMods |= Event.ALT_MASK; if (e instanceof MouseEvent && !ignoreOldMouseEvents()) { if (id == MouseEvent.MOUSE_PRESSED) oldID = Event.MOUSE_DOWN; else if (id == MouseEvent.MOUSE_RELEASED) oldID = Event.MOUSE_UP; else if (id == MouseEvent.MOUSE_MOVED) oldID = Event.MOUSE_MOVE; else if (id == MouseEvent.MOUSE_DRAGGED) oldID = Event.MOUSE_DRAG; else if (id == MouseEvent.MOUSE_ENTERED) oldID = Event.MOUSE_ENTER; else if (id == MouseEvent.MOUSE_EXITED) oldID = Event.MOUSE_EXIT; else // No analogous AWT 1.0 mouse event. return null; MouseEvent me = (MouseEvent) e; translated = new Event (target, when, oldID, me.getX (), me.getY (), 0, oldMods); } else if (e instanceof KeyEvent) { if (id == KeyEvent.KEY_PRESSED) oldID = Event.KEY_PRESS; else if (e.getID () == KeyEvent.KEY_RELEASED) oldID = Event.KEY_RELEASE; else // No analogous AWT 1.0 key event. return null; int oldKey = 0; int newKey = ((KeyEvent) e).getKeyCode (); switch (newKey) { case KeyEvent.VK_BACK_SPACE: oldKey = Event.BACK_SPACE; break; case KeyEvent.VK_CAPS_LOCK: oldKey = Event.CAPS_LOCK; break; case KeyEvent.VK_DELETE: oldKey = Event.DELETE; break; case KeyEvent.VK_DOWN: case KeyEvent.VK_KP_DOWN: oldKey = Event.DOWN; break; case KeyEvent.VK_END: oldKey = Event.END; break; case KeyEvent.VK_ENTER: oldKey = Event.ENTER; break; case KeyEvent.VK_ESCAPE: oldKey = Event.ESCAPE; break; case KeyEvent.VK_F1: oldKey = Event.F1; break; case KeyEvent.VK_F10: oldKey = Event.F10; break; case KeyEvent.VK_F11: oldKey = Event.F11; break; case KeyEvent.VK_F12: oldKey = Event.F12; break; case KeyEvent.VK_F2: oldKey = Event.F2; break; case KeyEvent.VK_F3: oldKey = Event.F3; break; case KeyEvent.VK_F4: oldKey = Event.F4; break; case KeyEvent.VK_F5: oldKey = Event.F5; break; case KeyEvent.VK_F6: oldKey = Event.F6; break; case KeyEvent.VK_F7: oldKey = Event.F7; break; case KeyEvent.VK_F8: oldKey = Event.F8; break; case KeyEvent.VK_F9: oldKey = Event.F9; break; case KeyEvent.VK_HOME: oldKey = Event.HOME; break; case KeyEvent.VK_INSERT: oldKey = Event.INSERT; break; case KeyEvent.VK_LEFT: case KeyEvent.VK_KP_LEFT: oldKey = Event.LEFT; break; case KeyEvent.VK_NUM_LOCK: oldKey = Event.NUM_LOCK; break; case KeyEvent.VK_PAUSE: oldKey = Event.PAUSE; break; case KeyEvent.VK_PAGE_DOWN: oldKey = Event.PGDN; break; case KeyEvent.VK_PAGE_UP: oldKey = Event.PGUP; break; case KeyEvent.VK_PRINTSCREEN: oldKey = Event.PRINT_SCREEN; break; case KeyEvent.VK_RIGHT: case KeyEvent.VK_KP_RIGHT: oldKey = Event.RIGHT; break; case KeyEvent.VK_SCROLL_LOCK: oldKey = Event.SCROLL_LOCK; break; case KeyEvent.VK_TAB: oldKey = Event.TAB; break; case KeyEvent.VK_UP: case KeyEvent.VK_KP_UP: oldKey = Event.UP; break; default: oldKey = ((KeyEvent) e).getKeyChar(); } translated = new Event (target, when, oldID, 0, 0, oldKey, oldMods); } } else if (e instanceof AdjustmentEvent) { AdjustmentEvent ae = (AdjustmentEvent) e; int type = ae.getAdjustmentType(); int oldType; if (type == AdjustmentEvent.BLOCK_DECREMENT) oldType = Event.SCROLL_PAGE_UP; else if (type == AdjustmentEvent.BLOCK_INCREMENT) oldType = Event.SCROLL_PAGE_DOWN; else if (type == AdjustmentEvent.TRACK) oldType = Event.SCROLL_ABSOLUTE; else if (type == AdjustmentEvent.UNIT_DECREMENT) oldType = Event.SCROLL_LINE_UP; else if (type == AdjustmentEvent.UNIT_INCREMENT) oldType = Event.SCROLL_LINE_DOWN; else oldType = type; translated = new Event(target, oldType, new Integer(ae.getValue())); } else if (e instanceof ActionEvent) translated = new Event (target, Event.ACTION_EVENT, ((ActionEvent) e).getActionCommand ()); return translated; } /** * Implementation of dispatchEvent. Allows trusted package classes * to dispatch additional events first. This implementation first * translates <code>e</code> to an AWT 1.0 event and sends the * result to {@link #postEvent}. If the AWT 1.0 event is not * handled, and events of type <code>e</code> are enabled for this * component, e is passed on to {@link #processEvent}. * * @param e the event to dispatch */ void dispatchEventImpl(AWTEvent e) { // Update the component's knowledge about the size. // Important: Please look at the big comment in ComponentReshapeEvent // to learn why we did it this way. If you change this code, make // sure that the peer->AWT bounds update still works. // (for instance: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29448 ) if (e instanceof ComponentReshapeEvent) { ComponentReshapeEvent reshape = (ComponentReshapeEvent) e; x = reshape.x; y = reshape.y; width = reshape.width; height = reshape.height; return; } // Retarget focus events before dispatching it to the KeyboardFocusManager // in order to handle lightweight components properly. boolean dispatched = false; if (! e.isFocusManagerEvent) { e = KeyboardFocusManager.retargetFocusEvent(e); dispatched = KeyboardFocusManager.getCurrentKeyboardFocusManager() .dispatchEvent(e); } if (! dispatched) { // Give toolkit a chance to dispatch the event // to globally registered listeners. Toolkit.getDefaultToolkit().globalDispatchEvent(e); if (newEventsOnly) { if (eventTypeEnabled(e.id)) processEvent(e); } else { Event oldEvent = translateEvent(e); if (oldEvent != null) postEvent (oldEvent); } if (peer != null) peer.handleEvent(e); } } /** * Tells whether or not an event type is enabled. */ boolean eventTypeEnabled (int type) { if (type > AWTEvent.RESERVED_ID_MAX) return true; switch (type) { case HierarchyEvent.HIERARCHY_CHANGED: return (hierarchyListener != null || (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0); case HierarchyEvent.ANCESTOR_MOVED: case HierarchyEvent.ANCESTOR_RESIZED: return (hierarchyBoundsListener != null || (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0); case ComponentEvent.COMPONENT_HIDDEN: case ComponentEvent.COMPONENT_MOVED: case ComponentEvent.COMPONENT_RESIZED: case ComponentEvent.COMPONENT_SHOWN: return (componentListener != null || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0); case KeyEvent.KEY_PRESSED: case KeyEvent.KEY_RELEASED: case KeyEvent.KEY_TYPED: return (keyListener != null || (eventMask & AWTEvent.KEY_EVENT_MASK) != 0); case MouseEvent.MOUSE_CLICKED: case MouseEvent.MOUSE_ENTERED: case MouseEvent.MOUSE_EXITED: case MouseEvent.MOUSE_PRESSED: case MouseEvent.MOUSE_RELEASED: return (mouseListener != null || (eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0); case MouseEvent.MOUSE_MOVED: case MouseEvent.MOUSE_DRAGGED: return (mouseMotionListener != null || (eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0); case MouseEvent.MOUSE_WHEEL: return (mouseWheelListener != null || (eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0); case FocusEvent.FOCUS_GAINED: case FocusEvent.FOCUS_LOST: return (focusListener != null || (eventMask & AWTEvent.FOCUS_EVENT_MASK) != 0); case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED: case InputMethodEvent.CARET_POSITION_CHANGED: return (inputMethodListener != null || (eventMask & AWTEvent.INPUT_METHOD_EVENT_MASK) != 0); case PaintEvent.PAINT: case PaintEvent.UPDATE: return (eventMask & AWTEvent.PAINT_EVENT_MASK) != 0; default: return false; } } /** * Returns <code>true</code> when this component and all of its ancestors * are visible, <code>false</code> otherwise. * * @return <code>true</code> when this component and all of its ancestors * are visible, <code>false</code> otherwise */ boolean isHierarchyVisible() { boolean visible = isVisible(); Component comp = parent; while (comp != null && visible) { comp = comp.parent; if (comp != null) visible = visible && comp.isVisible(); } return visible; } /** * Returns the mouse pointer position relative to this Component's * top-left corner. * * @return relative mouse pointer position * * @throws HeadlessException if in a headless environment */ public Point getMousePosition() throws HeadlessException { return getMousePositionHelper(true); } Point getMousePositionHelper(boolean allowChildren) throws HeadlessException { if (GraphicsEnvironment.isHeadless()) throw new HeadlessException("can't get mouse position" + " in headless environment"); if (!isShowing()) return null; Component parent = this; int windowRelativeXOffset = 0; int windowRelativeYOffset = 0; while (parent != null && !(parent instanceof Window)) { windowRelativeXOffset += parent.getX(); windowRelativeYOffset += parent.getY(); parent = parent.getParent(); } if (parent == null) return null; Window window = (Window) parent; if (!Toolkit.getDefaultToolkit() .getMouseInfoPeer().isWindowUnderMouse(window)) return null; PointerInfo info = MouseInfo.getPointerInfo(); Point mouseLocation = info.getLocation(); Point windowLocation = window.getLocationOnScreen(); int x = mouseLocation.x - windowLocation.x; int y = mouseLocation.y - windowLocation.y; if (!mouseOverComponent(window.getComponentAt(x, y), allowChildren)) return null; return new Point(x - windowRelativeXOffset, y - windowRelativeYOffset); } boolean mouseOverComponent(Component component, boolean allowChildren) { return component == this; } /** * This method is used to implement transferFocus(). CHILD is the child * making the request. This is overridden by Container; when called for an * ordinary component there is no child and so we always return null. * * FIXME: is this still needed, in light of focus traversal policies? * * @param child the component making the request * @return the next component to focus on */ Component findNextFocusComponent(Component child) { return null; } /** * Deserializes this component. This regenerates all serializable listeners * which were registered originally. * * @param s the stream to read from * @throws ClassNotFoundException if deserialization fails * @throws IOException if the stream fails */ private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException { s.defaultReadObject(); String key = (String) s.readObject(); while (key != null) { Object listener = s.readObject(); if ("componentL".equals(key)) addComponentListener((ComponentListener) listener); else if ("focusL".equals(key)) addFocusListener((FocusListener) listener); else if ("keyL".equals(key)) addKeyListener((KeyListener) listener); else if ("mouseL".equals(key)) addMouseListener((MouseListener) listener); else if ("mouseMotionL".equals(key)) addMouseMotionListener((MouseMotionListener) listener); else if ("inputMethodL".equals(key)) addInputMethodListener((InputMethodListener) listener); else if ("hierarchyL".equals(key)) addHierarchyListener((HierarchyListener) listener); else if ("hierarchyBoundsL".equals(key)) addHierarchyBoundsListener((HierarchyBoundsListener) listener); else if ("mouseWheelL".equals(key)) addMouseWheelListener((MouseWheelListener) listener); key = (String) s.readObject(); } } /** * Serializes this component. This ignores all listeners which do not * implement Serializable, but includes those that do. * * @param s the stream to write to * @throws IOException if the stream fails */ private void writeObject(ObjectOutputStream s) throws IOException { s.defaultWriteObject(); AWTEventMulticaster.save(s, "componentL", componentListener); AWTEventMulticaster.save(s, "focusL", focusListener); AWTEventMulticaster.save(s, "keyL", keyListener); AWTEventMulticaster.save(s, "mouseL", mouseListener); AWTEventMulticaster.save(s, "mouseMotionL", mouseMotionListener); AWTEventMulticaster.save(s, "inputMethodL", inputMethodListener); AWTEventMulticaster.save(s, "hierarchyL", hierarchyListener); AWTEventMulticaster.save(s, "hierarchyBoundsL", hierarchyBoundsListener); AWTEventMulticaster.save(s, "mouseWheelL", mouseWheelListener); s.writeObject(null); } // Nested classes. /** * This class fixes the bounds for a Heavyweight component that * is placed inside a Lightweight container. When the lightweight is * moved or resized, setBounds for the lightweight peer does nothing. * Therefore, it was never moved on the screen. This class is * attached to the lightweight, and it adjusts the position and size * of the peer when notified. * This is the same for show and hide. */ class HeavyweightInLightweightListener implements ComponentListener { /** * Constructor. Adds component listener to lightweight parent. * * @param parent - the lightweight container. */ public HeavyweightInLightweightListener(Container parent) { parent.addComponentListener(this); } /** * This method is called when the component is resized. * * @param event the <code>ComponentEvent</code> indicating the resize */ public void componentResized(ComponentEvent event) { // Nothing to do here, componentMoved will be called. } /** * This method is called when the component is moved. * * @param event the <code>ComponentEvent</code> indicating the move */ public void componentMoved(ComponentEvent event) { if (peer != null) peer.setBounds(x, y, width, height); } /** * This method is called when the component is made visible. * * @param event the <code>ComponentEvent</code> indicating the visibility */ public void componentShown(ComponentEvent event) { if (isShowing()) peer.show(); } /** * This method is called when the component is hidden. * * @param event the <code>ComponentEvent</code> indicating the visibility */ public void componentHidden(ComponentEvent event) { if (isShowing()) peer.hide(); } } /** * This class provides accessibility support for subclasses of container. * * @author Eric Blake (ebb9@email.byu.edu) * @since 1.3 * @status updated to 1.4 */ protected abstract class AccessibleAWTComponent extends AccessibleContext implements Serializable, AccessibleComponent { /** * Compatible with JDK 1.3+. */ private static final long serialVersionUID = 642321655757800191L; /** * Converts show/hide events to PropertyChange events, and is registered * as a component listener on this component. * * @serial the component handler */ protected ComponentListener accessibleAWTComponentHandler = new AccessibleAWTComponentHandler(); /** * Converts focus events to PropertyChange events, and is registered * as a focus listener on this component. * * @serial the focus handler */ protected FocusListener accessibleAWTFocusHandler = new AccessibleAWTFocusHandler(); /** * The default constructor. */ protected AccessibleAWTComponent() { Component.this.addComponentListener(accessibleAWTComponentHandler); Component.this.addFocusListener(accessibleAWTFocusHandler); } /** * Adds a global property change listener to the accessible component. * * @param l the listener to add * @see #ACCESSIBLE_NAME_PROPERTY * @see #ACCESSIBLE_DESCRIPTION_PROPERTY * @see #ACCESSIBLE_STATE_PROPERTY * @see #ACCESSIBLE_VALUE_PROPERTY * @see #ACCESSIBLE_SELECTION_PROPERTY * @see #ACCESSIBLE_TEXT_PROPERTY * @see #ACCESSIBLE_VISIBLE_DATA_PROPERTY */ public void addPropertyChangeListener(PropertyChangeListener l) { Component.this.addPropertyChangeListener(l); super.addPropertyChangeListener(l); } /** * Removes a global property change listener from this accessible * component. * * @param l the listener to remove */ public void removePropertyChangeListener(PropertyChangeListener l) { Component.this.removePropertyChangeListener(l); super.removePropertyChangeListener(l); } /** * Returns the accessible name of this component. It is almost always * wrong to return getName(), since it is not localized. In fact, for * things like buttons, this should be the text of the button, not the * name of the object. The tooltip text might also be appropriate. * * @return the name * @see #setAccessibleName(String) */ public String getAccessibleName() { return accessibleName; } /** * Returns a brief description of this accessible context. This should * be localized. * * @return a description of this component * @see #setAccessibleDescription(String) */ public String getAccessibleDescription() { return accessibleDescription; } /** * Returns the role of this component. * * @return the accessible role */ public AccessibleRole getAccessibleRole() { return AccessibleRole.AWT_COMPONENT; } /** * Returns a state set describing this component's state. * * @return a new state set * @see AccessibleState */ public AccessibleStateSet getAccessibleStateSet() { AccessibleStateSet s = new AccessibleStateSet(); if (Component.this.isEnabled()) s.add(AccessibleState.ENABLED); if (isFocusable()) s.add(AccessibleState.FOCUSABLE); if (isFocusOwner()) s.add(AccessibleState.FOCUSED); // Note: While the java.awt.Component has an 'opaque' property, it // seems that it is not added to the accessible state set here, even // if this property is true. However, it is handled for // javax.swing.JComponent, so we add it there. if (Component.this.isShowing()) s.add(AccessibleState.SHOWING); if (Component.this.isVisible()) s.add(AccessibleState.VISIBLE); return s; } /** * Returns the parent of this component, if it is accessible. * * @return the accessible parent */ public Accessible getAccessibleParent() { if (accessibleParent == null) { Container parent = getParent(); accessibleParent = parent instanceof Accessible ? (Accessible) parent : null; } return accessibleParent; } /** * Returns the index of this component in its accessible parent. * * @return the index, or -1 if the parent is not accessible * @see #getAccessibleParent() */ public int getAccessibleIndexInParent() { if (getAccessibleParent() == null) return -1; AccessibleContext context = ((Component) accessibleParent).getAccessibleContext(); if (context == null) return -1; for (int i = context.getAccessibleChildrenCount(); --i >= 0; ) if (context.getAccessibleChild(i) == Component.this) return i; return -1; } /** * Returns the number of children of this component which implement * Accessible. Subclasses must override this if they can have children. * * @return the number of accessible children, default 0 */ public int getAccessibleChildrenCount() { return 0; } /** * Returns the ith accessible child. Subclasses must override this if * they can have children. * * @return the ith accessible child, or null * @see #getAccessibleChildrenCount() */ public Accessible getAccessibleChild(int i) { return null; } /** * Returns the locale of this component. * * @return the locale * @throws IllegalComponentStateException if the locale is unknown */ public Locale getLocale() { return Component.this.getLocale(); } /** * Returns this, since it is an accessible component. * * @return the accessible component */ public AccessibleComponent getAccessibleComponent() { return this; } /** * Gets the background color. * * @return the background color * @see #setBackground(Color) */ public Color getBackground() { return Component.this.getBackground(); } /** * Sets the background color. * * @param c the background color * @see #getBackground() * @see #isOpaque() */ public void setBackground(Color c) { Component.this.setBackground(c); } /** * Gets the foreground color. * * @return the foreground color * @see #setForeground(Color) */ public Color getForeground() { return Component.this.getForeground(); } /** * Sets the foreground color. * * @param c the foreground color * @see #getForeground() */ public void setForeground(Color c) { Component.this.setForeground(c); } /** * Gets the cursor. * * @return the cursor * @see #setCursor(Cursor) */ public Cursor getCursor() { return Component.this.getCursor(); } /** * Sets the cursor. * * @param cursor the cursor * @see #getCursor() */ public void setCursor(Cursor cursor) { Component.this.setCursor(cursor); } /** * Gets the font. * * @return the font * @see #setFont(Font) */ public Font getFont() { return Component.this.getFont(); } /** * Sets the font. * * @param f the font * @see #getFont() */ public void setFont(Font f) { Component.this.setFont(f); } /** * Gets the font metrics for a font. * * @param f the font to look up * @return its metrics * @throws NullPointerException if f is null * @see #getFont() */ public FontMetrics getFontMetrics(Font f) { return Component.this.getFontMetrics(f); } /** * Tests if the component is enabled. * * @return true if the component is enabled * @see #setEnabled(boolean) * @see #getAccessibleStateSet() * @see AccessibleState#ENABLED */ public boolean isEnabled() { return Component.this.isEnabled(); } /** * Set whether the component is enabled. * * @param b the new enabled status * @see #isEnabled() */ public void setEnabled(boolean b) { Component.this.setEnabled(b); } /** * Test whether the component is visible (not necesarily showing). * * @return true if it is visible * @see #setVisible(boolean) * @see #getAccessibleStateSet() * @see AccessibleState#VISIBLE */ public boolean isVisible() { return Component.this.isVisible(); } /** * Sets the visibility of this component. * * @param b the desired visibility * @see #isVisible() */ public void setVisible(boolean b) { Component.this.setVisible(b); } /** * Tests if the component is showing. * * @return true if this is showing */ public boolean isShowing() { return Component.this.isShowing(); } /** * Tests if the point is contained in this component. * * @param p the point to check * @return true if it is contained * @throws NullPointerException if p is null */ public boolean contains(Point p) { return Component.this.contains(p.x, p.y); } /** * Returns the location of this object on the screen, or null if it is * not showing. * * @return the location relative to screen coordinates, if showing * @see #getBounds() * @see #getLocation() */ public Point getLocationOnScreen() { return Component.this.isShowing() ? Component.this.getLocationOnScreen() : null; } /** * Returns the location of this object relative to its parent's coordinate * system, or null if it is not showing. * * @return the location * @see #getBounds() * @see #getLocationOnScreen() */ public Point getLocation() { return Component.this.getLocation(); } /** * Sets the location of this relative to its parent's coordinate system. * * @param p the location * @throws NullPointerException if p is null * @see #getLocation() */ public void setLocation(Point p) { Component.this.setLocation(p.x, p.y); } /** * Gets the bounds of this component, or null if it is not on screen. * * @return the bounds * @see #contains(Point) * @see #setBounds(Rectangle) */ public Rectangle getBounds() { return Component.this.getBounds(); } /** * Sets the bounds of this component. * * @param r the bounds * @throws NullPointerException if r is null * @see #getBounds() */ public void setBounds(Rectangle r) { Component.this.setBounds(r.x, r.y, r.width, r.height); } /** * Gets the size of this component, or null if it is not showing. * * @return the size * @see #setSize(Dimension) */ public Dimension getSize() { return Component.this.getSize(); } /** * Sets the size of this component. * * @param d the size * @throws NullPointerException if d is null * @see #getSize() */ public void setSize(Dimension d) { Component.this.setSize(d.width, d.height); } /** * Returns the Accessible child at a point relative to the coordinate * system of this component, if one exists, or null. Since components * have no children, subclasses must override this to get anything besides * null. * * @param p the point to check * @return the accessible child at that point * @throws NullPointerException if p is null */ public Accessible getAccessibleAt(Point p) { return null; } /** * Tests whether this component can accept focus. * * @return true if this is focus traversable * @see #getAccessibleStateSet () * @see AccessibleState#FOCUSABLE * @see AccessibleState#FOCUSED */ public boolean isFocusTraversable () { return Component.this.isFocusTraversable (); } /** * Requests focus for this component. * * @see #isFocusTraversable () */ public void requestFocus () { Component.this.requestFocus (); } /** * Adds a focus listener. * * @param l the listener to add */ public void addFocusListener(FocusListener l) { Component.this.addFocusListener(l); } /** * Removes a focus listener. * * @param l the listener to remove */ public void removeFocusListener(FocusListener l) { Component.this.removeFocusListener(l); } /** * Converts component changes into property changes. * * @author Eric Blake (ebb9@email.byu.edu) * @since 1.3 * @status updated to 1.4 */ protected class AccessibleAWTComponentHandler implements ComponentListener { /** * Default constructor. */ protected AccessibleAWTComponentHandler() { // Nothing to do here. } /** * Convert a component hidden to a property change. * * @param e the event to convert */ public void componentHidden(ComponentEvent e) { AccessibleAWTComponent.this.firePropertyChange (ACCESSIBLE_STATE_PROPERTY, AccessibleState.VISIBLE, null); } /** * Convert a component shown to a property change. * * @param e the event to convert */ public void componentShown(ComponentEvent e) { AccessibleAWTComponent.this.firePropertyChange (ACCESSIBLE_STATE_PROPERTY, null, AccessibleState.VISIBLE); } /** * Moving a component does not affect properties. * * @param e ignored */ public void componentMoved(ComponentEvent e) { // Nothing to do here. } /** * Resizing a component does not affect properties. * * @param e ignored */ public void componentResized(ComponentEvent e) { // Nothing to do here. } } // class AccessibleAWTComponentHandler /** * Converts focus changes into property changes. * * @author Eric Blake (ebb9@email.byu.edu) * @since 1.3 * @status updated to 1.4 */ protected class AccessibleAWTFocusHandler implements FocusListener { /** * Default constructor. */ protected AccessibleAWTFocusHandler() { // Nothing to do here. } /** * Convert a focus gained to a property change. * * @param e the event to convert */ public void focusGained(FocusEvent e) { AccessibleAWTComponent.this.firePropertyChange (ACCESSIBLE_STATE_PROPERTY, null, AccessibleState.FOCUSED); } /** * Convert a focus lost to a property change. * * @param e the event to convert */ public void focusLost(FocusEvent e) { AccessibleAWTComponent.this.firePropertyChange (ACCESSIBLE_STATE_PROPERTY, AccessibleState.FOCUSED, null); } } // class AccessibleAWTComponentHandler } // class AccessibleAWTComponent /** * This class provides support for blitting offscreen surfaces to a * component. * * @see BufferStrategy * * @since 1.4 */ protected class BltBufferStrategy extends BufferStrategy { /** * The capabilities of the image buffer. */ protected BufferCapabilities caps; /** * The back buffers used in this strategy. */ protected VolatileImage[] backBuffers; /** * Whether or not the image buffer resources are allocated and * ready to be drawn into. */ protected boolean validatedContents; /** * The width of the back buffers. */ protected int width; /** * The height of the back buffers. */ protected int height; /** * The front buffer. */ private VolatileImage frontBuffer; /** * Creates a blitting buffer strategy. * * @param numBuffers the number of buffers, including the front * buffer * @param caps the capabilities of this strategy */ protected BltBufferStrategy(int numBuffers, BufferCapabilities caps) { this.caps = caps; createBackBuffers(numBuffers - 1); width = getWidth(); height = getHeight(); } /** * Initializes the backBuffers field with an array of numBuffers * VolatileImages. * * @param numBuffers the number of backbuffers to create */ protected void createBackBuffers(int numBuffers) { GraphicsConfiguration c = GraphicsEnvironment.getLocalGraphicsEnvironment() .getDefaultScreenDevice().getDefaultConfiguration(); backBuffers = new VolatileImage[numBuffers]; for (int i = 0; i < numBuffers; i++) backBuffers[i] = c.createCompatibleVolatileImage(width, height); } /** * Retrieves the capabilities of this buffer strategy. * * @return the capabilities of this buffer strategy */ public BufferCapabilities getCapabilities() { return caps; } /** * Retrieves a graphics object that can be used to draw into this * strategy's image buffer. * * @return a graphics object */ public Graphics getDrawGraphics() { // Return the backmost buffer's graphics. return backBuffers[0].getGraphics(); } /** * Bring the contents of the back buffer to the front buffer. */ public void show() { GraphicsConfiguration c = GraphicsEnvironment.getLocalGraphicsEnvironment() .getDefaultScreenDevice().getDefaultConfiguration(); // draw the front buffer. getGraphics().drawImage(backBuffers[backBuffers.length - 1], width, height, null); BufferCapabilities.FlipContents f = getCapabilities().getFlipContents(); // blit the back buffers. for (int i = backBuffers.length - 1; i > 0 ; i--) backBuffers[i] = backBuffers[i - 1]; // create new backmost buffer. if (f == BufferCapabilities.FlipContents.UNDEFINED) backBuffers[0] = c.createCompatibleVolatileImage(width, height); // create new backmost buffer and clear it to the background // color. if (f == BufferCapabilities.FlipContents.BACKGROUND) { backBuffers[0] = c.createCompatibleVolatileImage(width, height); backBuffers[0].getGraphics().clearRect(0, 0, width, height); } // FIXME: set the backmost buffer to the prior contents of the // front buffer. How do we retrieve the contents of the front // buffer? // // if (f == BufferCapabilities.FlipContents.PRIOR) // set the backmost buffer to a copy of the new front buffer. if (f == BufferCapabilities.FlipContents.COPIED) backBuffers[0] = backBuffers[backBuffers.length - 1]; } /** * Re-create the image buffer resources if they've been lost. */ protected void revalidate() { GraphicsConfiguration c = GraphicsEnvironment.getLocalGraphicsEnvironment() .getDefaultScreenDevice().getDefaultConfiguration(); for (int i = 0; i < backBuffers.length; i++) { int result = backBuffers[i].validate(c); if (result == VolatileImage.IMAGE_INCOMPATIBLE) backBuffers[i] = c.createCompatibleVolatileImage(width, height); } validatedContents = true; } /** * Returns whether or not the image buffer resources have been * lost. * * @return true if the resources have been lost, false otherwise */ public boolean contentsLost() { for (int i = 0; i < backBuffers.length; i++) { if (backBuffers[i].contentsLost()) { validatedContents = false; return true; } } // we know that the buffer resources are valid now because we // just checked them validatedContents = true; return false; } /** * Returns whether or not the image buffer resources have been * restored. * * @return true if the resources have been restored, false * otherwise */ public boolean contentsRestored() { GraphicsConfiguration c = GraphicsEnvironment.getLocalGraphicsEnvironment() .getDefaultScreenDevice().getDefaultConfiguration(); boolean imageRestored = false; for (int i = 0; i < backBuffers.length; i++) { int result = backBuffers[i].validate(c); if (result == VolatileImage.IMAGE_RESTORED) imageRestored = true; else if (result == VolatileImage.IMAGE_INCOMPATIBLE) return false; } // we know that the buffer resources are valid now because we // just checked them validatedContents = true; return imageRestored; } } /** * This class provides support for flipping component buffers. It * can only be used on Canvases and Windows. * * @since 1.4 */ protected class FlipBufferStrategy extends BufferStrategy { /** * The number of buffers. */ protected int numBuffers; /** * The capabilities of this buffering strategy. */ protected BufferCapabilities caps; /** * An Image reference to the drawing buffer. */ protected Image drawBuffer; /** * A VolatileImage reference to the drawing buffer. */ protected VolatileImage drawVBuffer; /** * Whether or not the image buffer resources are allocated and * ready to be drawn into. */ protected boolean validatedContents; /** * The width of the back buffer. */ private int width; /** * The height of the back buffer. */ private int height; /** * Creates a flipping buffer strategy. The only supported * strategy for FlipBufferStrategy itself is a double-buffer page * flipping strategy. It forms the basis for more complex derived * strategies. * * @param numBuffers the number of buffers * @param caps the capabilities of this buffering strategy * * @throws AWTException if the requested * number-of-buffers/capabilities combination is not supported */ protected FlipBufferStrategy(int numBuffers, BufferCapabilities caps) throws AWTException { this.caps = caps; width = getWidth(); height = getHeight(); if (numBuffers > 1) createBuffers(numBuffers, caps); else { drawVBuffer = peer.createVolatileImage(width, height); drawBuffer = drawVBuffer; } } /** * Creates a multi-buffer flipping strategy. The number of * buffers must be greater than one and the buffer capabilities * must specify page flipping. * * @param numBuffers the number of flipping buffers; must be * greater than one * @param caps the buffering capabilities; caps.isPageFlipping() * must return true * * @throws IllegalArgumentException if numBuffers is not greater * than one or if the page flipping capability is not requested * * @throws AWTException if the requested flipping strategy is not * supported */ protected void createBuffers(int numBuffers, BufferCapabilities caps) throws AWTException { if (numBuffers <= 1) throw new IllegalArgumentException("FlipBufferStrategy.createBuffers:" + " numBuffers must be greater than" + " one."); if (!caps.isPageFlipping()) throw new IllegalArgumentException("FlipBufferStrategy.createBuffers:" + " flipping must be a specified" + " capability."); peer.createBuffers(numBuffers, caps); } /** * Return a direct reference to the back buffer image. * * @return a direct reference to the back buffer image. */ protected Image getBackBuffer() { return peer.getBackBuffer(); } /** * Perform a flip operation to transfer the contents of the back * buffer to the front buffer. */ protected void flip(BufferCapabilities.FlipContents flipAction) { peer.flip(flipAction); } /** * Release the back buffer's resources. */ protected void destroyBuffers() { peer.destroyBuffers(); } /** * Retrieves the capabilities of this buffer strategy. * * @return the capabilities of this buffer strategy */ public BufferCapabilities getCapabilities() { return caps; } /** * Retrieves a graphics object that can be used to draw into this * strategy's image buffer. * * @return a graphics object */ public Graphics getDrawGraphics() { return drawVBuffer.getGraphics(); } /** * Re-create the image buffer resources if they've been lost. */ protected void revalidate() { GraphicsConfiguration c = GraphicsEnvironment.getLocalGraphicsEnvironment() .getDefaultScreenDevice().getDefaultConfiguration(); if (drawVBuffer.validate(c) == VolatileImage.IMAGE_INCOMPATIBLE) drawVBuffer = peer.createVolatileImage(width, height); validatedContents = true; } /** * Returns whether or not the image buffer resources have been * lost. * * @return true if the resources have been lost, false otherwise */ public boolean contentsLost() { if (drawVBuffer.contentsLost()) { validatedContents = false; return true; } // we know that the buffer resources are valid now because we // just checked them validatedContents = true; return false; } /** * Returns whether or not the image buffer resources have been * restored. * * @return true if the resources have been restored, false * otherwise */ public boolean contentsRestored() { GraphicsConfiguration c = GraphicsEnvironment.getLocalGraphicsEnvironment() .getDefaultScreenDevice().getDefaultConfiguration(); int result = drawVBuffer.validate(c); boolean imageRestored = false; if (result == VolatileImage.IMAGE_RESTORED) imageRestored = true; else if (result == VolatileImage.IMAGE_INCOMPATIBLE) return false; // we know that the buffer resources are valid now because we // just checked them validatedContents = true; return imageRestored; } /** * Bring the contents of the back buffer to the front buffer. */ public void show() { flip(caps.getFlipContents()); } } }