summaryrefslogtreecommitdiffstats
path: root/awt-kernel/src/main/java
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:28:47 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:28:47 -0800
commitadc854b798c1cfe3bfd4c27d68d5cee38ca617da (patch)
tree6aed8b4923ca428942cbaa7e848d50237a3d31e0 /awt-kernel/src/main/java
parent1c0fed63c71ddb230f3b304aac12caffbedf2f21 (diff)
downloadlibcore-adc854b798c1cfe3bfd4c27d68d5cee38ca617da.zip
libcore-adc854b798c1cfe3bfd4c27d68d5cee38ca617da.tar.gz
libcore-adc854b798c1cfe3bfd4c27d68d5cee38ca617da.tar.bz2
auto import from //depot/cupcake/@135843
Diffstat (limited to 'awt-kernel/src/main/java')
-rw-r--r--awt-kernel/src/main/java/java/awt/font/NumericShaper.java885
-rw-r--r--awt-kernel/src/main/java/java/awt/font/TextAttribute.java301
-rw-r--r--awt-kernel/src/main/java/java/beans/IndexedPropertyChangeEvent.java66
-rw-r--r--awt-kernel/src/main/java/java/beans/PropertyChangeEvent.java116
-rw-r--r--awt-kernel/src/main/java/java/beans/PropertyChangeListener.java38
-rw-r--r--awt-kernel/src/main/java/java/beans/PropertyChangeListenerProxy.java61
-rw-r--r--awt-kernel/src/main/java/java/beans/PropertyChangeSupport.java501
7 files changed, 1968 insertions, 0 deletions
diff --git a/awt-kernel/src/main/java/java/awt/font/NumericShaper.java b/awt-kernel/src/main/java/java/awt/font/NumericShaper.java
new file mode 100644
index 0000000..e8ea693
--- /dev/null
+++ b/awt-kernel/src/main/java/java/awt/font/NumericShaper.java
@@ -0,0 +1,885 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @author Ilya S. Okomin
+ * @version $Revision$
+ */
+package java.awt.font;
+
+import java.io.IOException;
+import java.io.Serializable;
+
+// BEGIN android-deleted
+//import org.apache.harmony.awt.internal.nls.Messages;
+// END android-deleted
+import org.apache.harmony.misc.HashCode;
+
+
+/**
+ * The Class NumericShaper provides methods to convert latin character codes
+ * to unicode character codes.
+ * For tables of the character codes used,
+ * see <a href="http://www.unicode.org/Public/UNIDATA/">unicode.org</a>.
+ */
+public final class NumericShaper implements Serializable {
+
+ /** The Constant serialVersionUID. */
+ private static final long serialVersionUID = -8022764705923730308L;
+
+ /**
+ * The Constant EUROPEAN indicates the latin and extended range,
+ * and latin decimal base.
+ */
+ public static final int EUROPEAN = 1;
+
+ /** The Constant ARABIC indicates the ARABIC range and decimal base. */
+ public static final int ARABIC = 2;
+
+ /**
+ * The Constant EASTERN_ARABIC indicates the ARABIC range and
+ * ARABIC_EXTENDED decimal base.
+ */
+ public static final int EASTERN_ARABIC = 4;
+
+ /**
+ * The Constant DEVANAGARI indicates the DEVANAGARI range and
+ * decimal base.
+ */
+ public static final int DEVANAGARI = 8;
+
+ /** The Constant BENGALI indicates the BENGALI range and decimal base. */
+ public static final int BENGALI = 16;
+
+ /** The Constant GURMUKHI indicates the GURMUKHI range and decimal base. */
+ public static final int GURMUKHI = 32;
+
+ /** The Constant GUJARATI indicates the GUJARATI range and decimal base. */
+ public static final int GUJARATI = 64;
+
+ /** The Constant ORIYA indicates the ORIYA range and decimal base. */
+ public static final int ORIYA = 128;
+
+ /** The Constant TAMIL indicates the TAMIL range and decimal base. */
+ public static final int TAMIL = 256;
+
+ /** The Constant TELUGU indicates the TELUGU range and decimal base. */
+ public static final int TELUGU = 512;
+
+ /** The Constant KANNADA indicates the KANNADA range and decimal base. */
+ public static final int KANNADA = 1024;
+
+ /**
+ * The Constant MALAYALAM indicates the MALAYALAM range and decimal base.
+ */
+ public static final int MALAYALAM = 2048;
+
+ /** The Constant THAI indicates the THAI range and decimal base. */
+ public static final int THAI = 4096;
+
+ /** The Constant LAO indicates the LAO range and decimal base. */
+ public static final int LAO = 8192;
+
+ /** The Constant TIBETAN indicates the TIBETAN range and decimal base. */
+ public static final int TIBETAN = 16384;
+
+ /** The Constant MYANMAR indicates the MYANMAR range and decimal base. */
+ public static final int MYANMAR = 32768;
+
+ /**
+ * The Constant ETHIOPIC indicates the ETHIOPIC range and decimal base.
+ */
+ public static final int ETHIOPIC = 65536;
+
+ /** The Constant KHMER indicates the KHMER range and decimal base. */
+ public static final int KHMER = 131072;
+
+ /**
+ * The Constant MONGOLIAN indicates the MONGOLIAN range and
+ * decimal base.
+ */
+ public static final int MONGOLIAN = 262144;
+
+ /** The Constant ALL_RANGES indicates all ranges. */
+ public static final int ALL_RANGES = 524287;
+
+ /* Further one can find the set of script indices.
+ * Index is the power you need the 2 to raise to to get corresponding
+ * range constant value. Also script ranges, context names and digits low
+ * ranges are indexed with these indices.
+ */
+
+ // Index of the EUROPEAN range
+ /** The Constant INDEX_EUROPEAN. */
+ private static final int INDEX_EUROPEAN = 0;
+
+ // Index of the ARABIC range
+ /** The Constant INDEX_ARABIC. */
+ private static final int INDEX_ARABIC = 1;
+
+ // Index of the EASTERN_ARABIC range
+ /** The Constant INDEX_EASTERN_ARABIC. */
+ private static final int INDEX_EASTERN_ARABIC = 2;
+
+ // Index of the DEVANAGARI range
+ /** The Constant INDEX_DEVANAGARI. */
+ private static final int INDEX_DEVANAGARI = 3;
+
+ // Index of the BENGALI range
+ /** The Constant INDEX_BENGALI. */
+ private static final int INDEX_BENGALI = 4;
+
+ // Index of the GURMUKHI range
+ /** The Constant INDEX_GURMUKHI. */
+ private static final int INDEX_GURMUKHI = 5;
+
+ // Index of the GUJARTI range
+ /** The Constant INDEX_GUJARATI. */
+ private static final int INDEX_GUJARATI = 6;
+
+ // Index of the ORIYA range
+ /** The Constant INDEX_ORIYA. */
+ private static final int INDEX_ORIYA = 7;
+
+ // Index of the TAMIL range
+ /** The Constant INDEX_TAMIL. */
+ private static final int INDEX_TAMIL = 8;
+
+ // Index of the TELUGU range
+ /** The Constant INDEX_TELUGU. */
+ private static final int INDEX_TELUGU = 9;
+
+ // Index of the KANNADA range
+ /** The Constant INDEX_KANNADA. */
+ private static final int INDEX_KANNADA = 10;
+
+ // Index of the MALAYALAM range
+ /** The Constant INDEX_MALAYALAM. */
+ private static final int INDEX_MALAYALAM = 11;
+
+ // Index of the THAI range
+ /** The Constant INDEX_THAI. */
+ private static final int INDEX_THAI = 12;
+
+ // Index of the LAO range
+ /** The Constant INDEX_LAO. */
+ private static final int INDEX_LAO = 13;
+
+ // Index of the TIBETAN range
+ /** The Constant INDEX_TIBETAN. */
+ private static final int INDEX_TIBETAN = 14;
+
+ // Index of the MYANMAR range
+ /** The Constant INDEX_MYANMAR. */
+ private static final int INDEX_MYANMAR = 15;
+
+ // Index of the ETHIOPIC range
+ /** The Constant INDEX_ETHIOPIC. */
+ private static final int INDEX_ETHIOPIC = 16;
+
+ // Index of the KHMER range
+ /** The Constant INDEX_KHMER. */
+ private static final int INDEX_KHMER = 17;
+
+ // Index of the MONGOLIAN range
+ /** The Constant INDEX_MONGOLIAN. */
+ private static final int INDEX_MONGOLIAN = 18;
+
+ // Maximum index that range can't exceed
+ /** The Constant MAX_INDEX. */
+ private static final int MAX_INDEX = 19;
+
+ /*
+ * Scripts ranges array. Array represents ranges as pairs of
+ * lowest and highest range bounds.
+ * Data is taken from the UnicodeData.txt file from
+ * http://www.unicode.org/Public/UNIDATA/
+ */
+ /** The scripts ranges. */
+ private final int[] scriptsRanges = {
+ 0x0000, 0x024F, // EUROPEAN (basic latin + latin-1 + extended)
+ 0x0600, 0x06FF, // ARABIC
+ 0x0600, 0x06FF, // EASTERN_ARABIC (XXX: diff with ARABIC ? )
+ 0x0900, 0x097F, // DEVANAGARI
+ 0x0980, 0x09FF, // BENGALI
+ 0x0A00, 0x0A7F, // GURMUKHI
+ 0x0A80, 0x0AFF, // GUJARATI
+ 0x0B00, 0x0B7F, // ORIYA
+ 0x0B80, 0x0BFF, // TAMIL
+ 0x0C00, 0x0C7F, // TELUGU
+ 0x0C80, 0x0CFF, // KANNADA
+ 0x0D00, 0x0D7F, // MALAYALAM
+ 0x0E00, 0x0E7F, // THAI
+ 0x0E80, 0x0EFF, // LAO
+ 0x0F00, 0x0FFF, // TIBETAN
+ 0x1000, 0x109F, // MYANMAR
+ 0x1200, 0x137F, // ETHIOPIC
+ 0x1780, 0x17FF, // KHMER
+ 0x1800, 0x18AF // MONGOLIAN
+ };
+
+ /*
+ * Digit low ranges values decreased by 0x0030. Each low range
+ * value decreased by 0x0030 for easy obtaing unicode value of the
+ * context dependent digit. European digits starts from 0x0030 hence
+ * context dependent unicode digit value equals to
+ * digitsLowRanges[script index] + european digit char unicode value.
+ * !! the only exception is ETHIOPIC script where there is no '0' digit
+ * Data is taken from the UnicodeData.txt file from
+ * http://www.unicode.org/Public/UNIDATA/
+ */
+ /** The digits low ranges. */
+ private final int[] digitsLowRanges = {
+ 0x0000, // EUROPEAN
+ 0x0630, // ARABIC
+ 0x0630, // EASTERN_ARABIC
+ 0x0936, // DEVANAGARI
+ 0x09B6, // BENGALI
+ 0x0A36, // GURMUKHI
+ 0x0AB6, // GUJARATI
+ 0x0B36, // ORIYA
+ 0x0BB6, // TAMIL
+ 0x0C36, // TELUGU
+ 0x0CB6, // KANNADA
+ 0x0D36, // MALAYALAM
+ 0x0E20, // THAI
+ 0x0EA0, // LAO
+ 0x0EF0, // TIBETAN
+ 0x1010, // MYANMAR
+ 0x1338, // ETHIOPIC - (low range-1) no ETHIOPIC '0' DIGIT!
+ 0x17B0, // KHMER
+ 0x17E0 // MONGOLIAN
+ };
+
+ // Set of context names used in toString method
+ /** The contexts. */
+ private final String[] contexts = {
+ "EUROPEAN", //$NON-NLS-1$
+ "ARABIC", //$NON-NLS-1$
+ "EASTERN_ARABIC", //$NON-NLS-1$
+ "DEVANAGARI", //$NON-NLS-1$
+ "BENGALI", //$NON-NLS-1$
+ "GURMUKHI", //$NON-NLS-1$
+ "GUJARATI", //$NON-NLS-1$
+ "ORIYA", //$NON-NLS-1$
+ "TAMIL", //$NON-NLS-1$
+ "TELUGU", //$NON-NLS-1$
+ "KANNADA", //$NON-NLS-1$
+ "MALAYALAM", //$NON-NLS-1$
+ "THAI", //$NON-NLS-1$
+ "LAO", //$NON-NLS-1$
+ "TIBETAN", //$NON-NLS-1$
+ "MYANMAR", //$NON-NLS-1$
+ "ETHIOPIC", //$NON-NLS-1$
+ "KHMER", //$NON-NLS-1$
+ "MONGOLIAN" //$NON-NLS-1$
+ };
+
+ /*
+ * Strong characters flags array is to determine if the
+ * unicode bidirectional category of the character is strong,
+ * according to Unicode specification. If the bit with index equals to
+ * character's unicode value is 1 - the character is strong.
+ * This array was generated using UnicodeData.txt file from
+ * http://www.unicode.org/Public/UNIDATA/
+ */
+
+ /** The Constant STRONG_TEXT_FLAGS. */
+ private static final int[] STRONG_TEXT_FLAGS = { 0, 0, 134217726, 134217726,
+ 0, 69207040, -8388609, -8388609, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -65533, -1, -1, -100663297, 196611, 16415, 0, 0, 0,
+ 67108864, -10432, -5, -32769, -4194305, -1, -1, -1, -1, -1017, -1,
+ -32769, 67108863, 65535, -131072, -25165825, -2, 767, 1073741824,
+ -65463, 2033663, -939513841, 134217726, 2047, -73728, -1, -1,
+ 541065215, -67059616, -180225, 65535, -8192, 16383, -1, 131135, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -8, -469762049, -16703999, 537001971,
+ -417812, -473563649, -1333765759, 133431235, -423960, -1016201729,
+ 1577058305, 1900480, -278552, -470942209, 72193, 65475, -417812,
+ 1676541439, -1333782143, 262083, -700594200, -1006647528, 8396230,
+ 524224, -139282, 66059775, 30, 65475, -139284, -470811137,
+ 1080036831, 65475, -139284, -1006633473, 8396225, 65475, -58720276,
+ 805044223, -16547713, 1835008, -2, 917503, 268402815, 0, -17816170,
+ 537783470, 872349791, 0, -50331649, -1050673153, -257, -2147481601,
+ 3872, -1073741824, 237503, 0, -1, 16914171, 16777215, 0, 0, -1,
+ -65473, 536870911, -1, -1, -2080374785, -1, -1, -249, -1, 67108863,
+ -1, -1, 1031749119, -1, -49665, 2134769663, -8388803, -1,
+ -12713985, -1, 134217727, 536870911, 65535, -1, -1, 2097151, -2,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 8388607, 134217726, -1, -1, 131071, 253951, 6553599, 262143,
+ 122879, -1, -1065353217, 401605055, 1023, 67043328, -1, -1,
+ 16777215, -1, 511, 0, 0, 536870911, 33226872, -64, 2047999, -1,
+ -64513, 67044351, 0, -830472193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, 0, 0,
+ -1, -1, -1, -1, 268435455, -1, -1, 67108863, 1061158911, -1,
+ -1426112705, 1073741823, -1, 1608515583, 265232348, 534519807,
+ 49152, 27648, 0, -2147352576, 2031616, 0, 0, 0, 1043332228,
+ -201605808, 992, -1, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -4194304, -1, 134217727, 2097152, 0, 0, 0, 0, 0, 0, 0, -268435456,
+ -1, -1, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4096, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1,
+ -32769, 2147483647, 0, -1, -1, -1, 31, -1, -65473, -1, 32831,
+ 8388607, 2139062143, 2139062143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 224, 524157950, -2, -1, -528482305, -2, -1,
+ -134217729, -32, -122881, -1, -1, -32769, 16777215, 0, -65536,
+ 536870911, -1, 15, -1879048193, -1, 131071, -61441, 2147483647, -1,
+ -1, -1, -125829121, -1, -1, 1073741823, 2147483647, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 2097152, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 134217728, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 8191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2117, 159, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 8, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2147483648, 1, 0, 0, -2147483648,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -2147483648, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2147483648, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -49153, -1, -63489, -1, -1, 67108863, 0,
+ -1594359681, 1602223615, -37, -1, -1, 262143, -524288, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1073741823, -65536, -1, -196609, -1,
+ 255, 536805376, 0, 0, 0, -2162688, -1, -1, -1, 536870911, 0,
+ 134217726, 134217726, -64, -1, 2147483647, 486341884, 0
+
+ };
+
+ // index of context range (Serialization support)
+ /** The key. */
+ private int key;
+
+ // flag, true if shaping contextual (Serialization support)
+ /** The mask. */
+ private int mask;
+
+ // ranges to be shaped
+ /** The ranges. */
+ private int fRanges;
+
+ // index of the default context
+ /** The default context index. */
+ private int fDefaultContextIndex;
+
+ // flag if NumericShaper shapes contextually
+ /** The contextual. */
+ private boolean fContextual;
+
+ // uses for non-context dependent case only
+ /** The single range index. */
+ private int fSingleRangeIndex;
+
+ /**
+ * Creates NumericShaper with specified parameters.
+ *
+ * @param ranges specified ranges to be shaped
+ * @param defaultContext default context range
+ * @param isContextual specifies if the instance is contextual
+ */
+ private NumericShaper(int ranges, int defaultContext, boolean isContextual){
+ this.fRanges = ranges;
+ this.fDefaultContextIndex = getIndexFromRange(defaultContext);
+ this.fContextual = isContextual;
+
+ if (!fContextual){
+ fSingleRangeIndex = getIndexFromRange(ranges);
+ }
+ }
+
+ /**
+ * Returns script index of the specified context range.
+ *
+ * @param range specified range
+ *
+ * @return one of the script indices according to the specified range.
+ */
+ private int getIndexFromRange(int range){
+ if (range == 0){
+ // BEGIN android-changed
+ throwRange(range);
+ // END android-changed
+ }
+
+ int index = 0;
+ while (index < MAX_INDEX){
+ if (range == (1 << index)){
+ return index;
+ }
+ index++;
+ }
+
+ // BEGIN android-changed
+ throwRange(range);
+ return -1; // Never executed; quiets the compiler.
+ // END android-changed
+ }
+
+ /**
+ * Returns range corresponding to the specified script index.
+ *
+ * @param index specified script index
+ *
+ * @return one of the range constants according to the specified script index.
+ */
+ private int getRangeFromIndex(int index){
+ if (index < 0 || index >= MAX_INDEX){
+ // BEGIN android-changed
+ throwRange(index);
+ // END android-changed
+ }
+
+ return 1 << index;
+ }
+
+ // BEGIN android-added
+ /**
+ * Throws a standard "out of range" exception.
+ *
+ * @param value the bogus value
+ */
+ private static void throwRange(int value) {
+ throw new IllegalArgumentException(
+ "Illegal range argument value: " + value);
+ }
+ // END android-added
+
+ /**
+ * Returns a hash code of this NumericShaper.
+ *
+ * @return a hash code of this NumericShaper.
+ */
+ @Override
+ public int hashCode() {
+ HashCode hash = new HashCode();
+
+ hash.append(fRanges);
+ hash.append(fDefaultContextIndex);
+ hash.append(fContextual);
+
+ return hash.hashCode();
+
+ }
+
+ /**
+ * Compares this NumericShaper object with the specified Object.
+ *
+ * @param obj the Object to be compared.
+ *
+ * @return true, if this NumericShaper object is equal to
+ * the specified Object, false otherwise.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+
+ if (obj == this) {
+ return true;
+ }
+
+ try {
+ NumericShaper ns = (NumericShaper)obj;
+ return (fRanges == ns.fRanges &&
+ fDefaultContextIndex == ns.fDefaultContextIndex &&
+ fContextual == ns.fContextual);
+ } catch (ClassCastException e){
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns a string representation of this NumericShaper.
+ *
+ * @return the string representation of this NumericShaper.
+ */
+ @Override
+ public String toString() {
+ /* !! There is no description in the documentation what this method must
+ * return. Thus format of toString method is based on 1.5 release
+ * behavior and can be obtained using next test sample:
+ *
+ * // Simple shapers toString format
+ * System.out.println(NumericShaper.getShaper(NumericShaper.EASTERN_ARABIC));
+ *
+ * // Context shapers with default context toString format
+ * System.out.println(NumericShaper.getContextualShaper(
+ * NumericShaper.ARABIC | NumericShaper.TAMIL));
+ *
+ * // Context shapers with context
+ * System.out.println(NumericShaper.getContextualShaper(
+ * NumericShaper.ARABIC | NumericShaper.TAMIL,
+ * NumericShaper.EASTERN_ARABIC));
+ */
+ StringBuffer sb = new StringBuffer(super.toString());
+
+ sb.append("[contextual:"); //$NON-NLS-1$
+ sb.append(fContextual);
+
+ if (fContextual){
+ sb.append(", context:"); //$NON-NLS-1$
+ sb.append(contexts[fDefaultContextIndex]);
+ }
+
+ sb.append(", range(s): "); //$NON-NLS-1$
+ if (fContextual) {
+ int index = 0;
+ boolean isFirst = true;
+ while (index < MAX_INDEX){
+ if ((fRanges & (1 << index)) != 0){
+ if (isFirst){
+ isFirst = false;
+ } else {
+ sb.append(", "); //$NON-NLS-1$
+ }
+ sb.append(contexts[index]);
+ }
+ index++;
+ }
+ } else {
+ sb.append(contexts[fSingleRangeIndex]);
+ }
+ sb.append("]"); //$NON-NLS-1$
+
+ return sb.toString();
+ }
+
+ /**
+ * Gets the NumericShaper for the specified unicode ranges
+ * and default unicode range. The defaultContext parameter
+ * is used as the starting context (which indicates the
+ * language/script being used). The OR logical operation
+ * should be used for multiple ranges:
+ * NumericShaper.DEVANAGARI | NumericShaper.BENGALI.
+ * The NumericShaper returned by this method is contextual
+ * in that it supports multiple character ranges, depending
+ * on the context.
+ *
+ * @param ranges the unicode ranges.
+ * @param defaultContext the default, starting context.
+ *
+ * @return the NumericShaper for the specified ranges.
+ */
+ public static NumericShaper getContextualShaper(int ranges,
+ int defaultContext) {
+ ranges &= ALL_RANGES;
+ defaultContext &= ALL_RANGES;
+ return new NumericShaper(ranges, defaultContext, true);
+ }
+
+ /**
+ * Gets the NumericShaper for the specified unicode ranges.
+ * The OR logical operation should be used for multiple ranges:
+ * NumericShaper.DEVANAGARI | NumericShaper.BENGALI.
+ * The NumericShaper returned by this method is contextual
+ * in that it supports multiple character ranges, depending
+ * on the context.
+ *
+ * @param ranges the unicode ranges.
+ *
+ * @return the NumericShaper for the specified ranges.
+ */
+ public static NumericShaper getContextualShaper(int ranges) {
+ ranges &= ALL_RANGES;
+ return new NumericShaper(ranges, EUROPEAN, true);
+ }
+
+ /**
+ * Gets the masks for all of the ranges supported by this NumericShaper,
+ * packed into an int value using the logical OR logical operation
+ * for multiple ranges:
+ * NumericShaper.DEVANAGARI | NumericShaper.BENGALI.
+ *
+ * @return all ranges of this NumericShaper.
+ */
+ public int getRanges() {
+ return fRanges;
+ }
+
+ /**
+ * Gets a NumericShaper for the specified unicode range.
+ * The NumericShaper supports only a single range and
+ * hence is not contextual.
+ *
+ * @param singleRange the specified unicode single range.
+ *
+ * @return the NumericShaper for the specified unicode range.
+ */
+ public static NumericShaper getShaper(int singleRange) {
+ singleRange &= ALL_RANGES;
+ return new NumericShaper(singleRange, EUROPEAN, false);
+ }
+
+ /**
+ * Checks if this NumericShaper is contextual (supporting
+ * multiple script ranges) or not.
+ *
+ * @return true, if this NumericShaper is contextual, false otherwise.
+ */
+ public boolean isContextual() {
+ return fContextual;
+ }
+
+ /**
+ * Transforms the encoding of the text, starting from the character
+ * at index start and transforming count characters,
+ * using the specified context.
+ *
+ * @param text the text to be shaped.
+ * @param start the start offset of the text.
+ * @param count the number of characters to be shaped.
+ * @param context the context to be used for shaping.
+ */
+ public void shape(char[] text, int start, int count, int context) {
+ if (isContextual()){
+ contextualShape(text, start, count, getIndexFromRange(context));
+ } else {
+ nonContextualShape(text, start, count);
+ }
+ }
+
+ /**
+ * Transforms the encoding of the text, starting from the character
+ * at index start and transforming count characters.
+ *
+ * @param text the text to be shaped.
+ * @param start the start offset of the text.
+ * @param count the number of characters to be shaped.
+ */
+ public void shape(char[] text, int start, int count) {
+ if (isContextual()){
+ contextualShape(text, start, count, fDefaultContextIndex);
+ } else {
+ nonContextualShape(text, start, count);
+ }
+ }
+
+ /**
+ * Converts count of digits of the given array of characters from the start
+ * index using specified context. This method is applied for the contextual
+ * shaping, if the shaper instance is not contextual use nonContextualShape
+ * method.
+ *
+ * @param text an array of chars
+ * @param start index of the first character to convert
+ * @param count a number of characters to convert
+ * @param contextIndex index of the script index to use in shaper
+ */
+ private void contextualShape(char[] text, int start, int count,
+ int contextIndex){
+ char maxDigit = (char)0x0039;
+ char minDigit = (char)0x0030;
+
+ int currIndex;
+ if (((1 << contextIndex) & fRanges) == 0 ){
+ currIndex = INDEX_EUROPEAN;
+ } else {
+ currIndex = contextIndex;
+ }
+
+ for (int ind = start; ind < start + count; ind++){
+ if (minDigit <= text[ind] && text[ind] <= maxDigit){
+ if (currIndex != INDEX_ETHIOPIC || text[ind] != '0'){
+ text[ind] = (char)(digitsLowRanges[currIndex] + text[ind]);
+ }
+ } else {
+ if(isCharStrong(text[ind])){
+ int index = getCharIndex(text[ind]);
+ if (currIndex != index){
+ if (((1 << index) & fRanges) != 0){
+ currIndex = index;
+ } else {
+ currIndex = INDEX_EUROPEAN;
+ }
+ }
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Converts count of digits of the given array of characters from the start
+ * index. Method is applied for non-contextual shaper.
+ *
+ * @param text an array of chars
+ * @param start index of the first character to convert
+ * @param count a number of characters to convert
+ */
+ private void nonContextualShape(char[] text, int start, int count){
+ char maxDigit = (char)0x0039;
+ char minDigit = (char)((fRanges == ETHIOPIC) ? 0x0031 : 0x0030);
+ for (int ind = start; ind < start + count; ind++){
+ if (minDigit <= text[ind] && text[ind] <= maxDigit){
+ text[ind] = (char)(digitsLowRanges[fSingleRangeIndex] + text[ind]);
+ }
+ }
+
+ }
+
+ /**
+ * Returns the index of the script of the specified char.
+ *
+ * @param ch specified unicode character
+ *
+ * @return script index corresponding to the given char
+ */
+ private int getCharIndex(char ch){
+ int index = INDEX_EUROPEAN;
+ for (int i=0; i < MAX_INDEX; i++){
+ int j = i * 2;
+ if (scriptsRanges[j] <= ch && ch <= scriptsRanges[j+1]){
+ return i;
+ }
+ }
+
+ return index;
+ }
+
+ /**
+ * Returns true if the bidirectional category of the character
+ * is strong.
+ *
+ * @param chr the chr
+ *
+ * @return true, if the character is strong, false otherwise
+ */
+ private boolean isCharStrong(int chr) {
+ return (STRONG_TEXT_FLAGS[chr >> 5] & (1 << (chr % 32))) != 0;
+ }
+
+ /**
+ * Updates all private serialized fields for object to be correctly serialized
+ * according to the serialized form of this class mentioned in the
+ * documentation.
+ */
+ private void updateRangesFields(){
+ fRanges = (mask & ~(1 << 31));
+ fContextual = ((mask &(1 << 31)) != 0);
+ if (fContextual){
+ fRanges = (mask & ~(1 << 31));
+ fDefaultContextIndex = key;
+ } else {
+ fRanges = mask;
+ fSingleRangeIndex = key;
+ }
+ }
+
+ /**
+ * Updates private fields for object after deserialization
+ * according to the serialized form of this class mentioned in the
+ * documentation.
+ */
+ private void updateKeyMaskFields(){
+ mask = fRanges;
+ if (fContextual){
+ mask |= (1 << 31);
+ key = fDefaultContextIndex;
+ } else{
+ key = fSingleRangeIndex;
+ }
+ }
+
+ /**
+ * Write object.
+ *
+ * @param out the out
+ *
+ * @throws IOException Signals that an I/O exception has occurred.
+ */
+ private void writeObject(java.io.ObjectOutputStream out)
+ throws IOException{
+ updateKeyMaskFields();
+ out.defaultWriteObject();
+ }
+
+ /**
+ * Read object.
+ *
+ * @param in the in
+ *
+ * @throws IOException Signals that an I/O exception has occurred.
+ * @throws ClassNotFoundException the class not found exception
+ */
+ private void readObject(java.io.ObjectInputStream in)
+ throws IOException, ClassNotFoundException{
+ in.defaultReadObject();
+ updateRangesFields();
+ }
+
+}
+
diff --git a/awt-kernel/src/main/java/java/awt/font/TextAttribute.java b/awt-kernel/src/main/java/java/awt/font/TextAttribute.java
new file mode 100644
index 0000000..aa1394a
--- /dev/null
+++ b/awt-kernel/src/main/java/java/awt/font/TextAttribute.java
@@ -0,0 +1,301 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @author Ilya S. Okomin
+ * @version $Revision$
+ */
+package java.awt.font;
+
+import java.io.InvalidObjectException;
+import java.text.AttributedCharacterIterator.Attribute;
+import java.util.HashMap;
+import java.util.Map;
+
+// BEGIN android-deleted
+//import org.apache.harmony.awt.internal.nls.Messages;
+// END android-deleted
+
+/**
+ * The TextAttribute class defines attribute keys and attribute values
+ * for text rendering. Each TextAttributes should have the following
+ * information:
+ * <ul>
+ * <li>key name;</li>
+ * <li>valid values;</li>
+ * <li>relevant constants;</li>
+ * <li>default action if the attribute is absent;</li>
+ * <li>default action's description.</li>
+ * </ul>
+ */
+public final class TextAttribute extends Attribute {
+
+ /** The Constant serialVersionUID. */
+ private static final long serialVersionUID = 7744112784117861702L;
+
+ // set of available text attributes
+ /** The Constant attrMap. */
+ private static final Map<String, TextAttribute> attrMap = new HashMap<String, TextAttribute>();
+
+ /**
+ * Instantiates a new TextAttribute with the specified name.
+ *
+ * @param name the name of TextAttribute.
+ */
+ protected TextAttribute(String name) {
+ super(name);
+ attrMap.put(name, this);
+ }
+
+ /**
+ * Resolves the instance being deserialized.
+ *
+ * @return the Object.
+ *
+ * @throws InvalidObjectException the InvalidObjectException.
+ */
+ @Override
+ protected Object readResolve() throws InvalidObjectException {
+ TextAttribute result = attrMap.get(this.getName());
+ if (result != null) {
+ return result;
+ }
+ // BEGIN android-changed
+ throw new InvalidObjectException("Unknown attribute name");
+ // END android-changed
+ }
+
+ /**
+ * The BACKGROUND text attribute.
+ */
+ public static final TextAttribute BACKGROUND = new TextAttribute("background"); //$NON-NLS-1$
+
+ /** The BIDI_EMBEDDING text attribute key. */
+ public static final TextAttribute BIDI_EMBEDDING = new TextAttribute("bidi_embedding"); //$NON-NLS-1$
+
+ /** The CHAR_REPLACEMENT text attribute key. */
+ public static final TextAttribute CHAR_REPLACEMENT = new TextAttribute("char_replacement"); //$NON-NLS-1$
+
+ /** The FAMILY text attribute key. */
+ public static final TextAttribute FAMILY = new TextAttribute("family"); //$NON-NLS-1$
+
+ /** The FONT text attribute key. */
+ public static final TextAttribute FONT = new TextAttribute("font"); //$NON-NLS-1$
+
+ /** The FOREGROUND text attribute key. */
+ public static final TextAttribute FOREGROUND = new TextAttribute("foreground"); //$NON-NLS-1$
+
+ /** The INPUT_METHOD_HIGHLIGHT text attribute key. */
+ public static final TextAttribute INPUT_METHOD_HIGHLIGHT = new TextAttribute(
+ "input method highlight"); //$NON-NLS-1$
+
+ /** The INPUT_METHOD_UNDERLINE text attribute key. */
+ public static final TextAttribute INPUT_METHOD_UNDERLINE = new TextAttribute(
+ "input method underline"); //$NON-NLS-1$
+
+ /** The JUSTIFICATION text attribute key. */
+ public static final TextAttribute JUSTIFICATION = new TextAttribute("justification"); //$NON-NLS-1$
+
+ /** The Constant JUSTIFICATION_indicates the full requested width. */
+ public static final Float JUSTIFICATION_FULL = new Float(1.0f);
+
+ /**
+ * The Constant JUSTIFICATION_NONE indicates that line is not
+ * allowed for justification.
+ */
+ public static final Float JUSTIFICATION_NONE = new Float(0.0f);
+
+ /** The NUMERIC_SHAPING text attribute. */
+ public static final TextAttribute NUMERIC_SHAPING = new TextAttribute("numeric_shaping"); //$NON-NLS-1$
+
+ /** The POSTURE text attribute. */
+ public static final TextAttribute POSTURE = new TextAttribute("posture"); //$NON-NLS-1$
+
+ /** The Constant POSTURE_REGULAR indicates regular posture. */
+ public static final Float POSTURE_REGULAR = new Float(0.0f);
+
+ /** The Constant POSTURE_OBLIQUE indicates italic posture. */
+ public static final Float POSTURE_OBLIQUE = new Float(0.20f);
+
+ /** The RUN_DIRECTION text attribute. */
+ public static final TextAttribute RUN_DIRECTION = new TextAttribute("run_direction"); //$NON-NLS-1$
+
+ /**
+ * The Constant RUN_DIRECTION_LTR indicates left-to-right run
+ * direction.
+ */
+ public static final Boolean RUN_DIRECTION_LTR = new Boolean(false);
+
+ /**
+ * The Constant RUN_DIRECTION_RTL indicates right-to-left run
+ * direction.
+ */
+ public static final Boolean RUN_DIRECTION_RTL = new Boolean(true);
+
+ /** The SIZE text attribute. */
+ public static final TextAttribute SIZE = new TextAttribute("size"); //$NON-NLS-1$
+
+ /** The STRIKETHROUGH text attribute. */
+ public static final TextAttribute STRIKETHROUGH = new TextAttribute("strikethrough"); //$NON-NLS-1$
+
+ /** The Constant STRIKETHROUGH_ON indicates a single strikethrough. */
+ public static final Boolean STRIKETHROUGH_ON = new Boolean(true);
+
+ /** The SUPERSCRIPT text attribute. */
+ public static final TextAttribute SUPERSCRIPT = new TextAttribute("superscript"); //$NON-NLS-1$
+
+ /** The Constant SUPERSCRIPT_SUB indicates a standard subscript. */
+ public static final Integer SUPERSCRIPT_SUB = new Integer(-1);
+
+ /** The Constant SUPERSCRIPT_SUPER indicates a standard superscript. */
+ public static final Integer SUPERSCRIPT_SUPER = new Integer(1);
+
+ /** The SWAP_COLORS text attribute. */
+ public static final TextAttribute SWAP_COLORS = new TextAttribute("swap_colors"); //$NON-NLS-1$
+
+ /**
+ * The Constant SWAP_COLORS_ON indicates a swap of foreground
+ * and background.
+ */
+ public static final Boolean SWAP_COLORS_ON = new Boolean(true);
+
+ /** The TRANSFORM text attribute. */
+ public static final TextAttribute TRANSFORM = new TextAttribute("transform"); //$NON-NLS-1$
+
+ /** The Constant UNDERLINE text attribute. */
+ public static final TextAttribute UNDERLINE = new TextAttribute("underline"); //$NON-NLS-1$
+
+ /**
+ * The Constant UNDERLINE_ON indicates a standard underline
+ * at the roman baseline for roman text.
+ */
+ public static final Integer UNDERLINE_ON = new Integer(0);
+
+ /**
+ * The Constant UNDERLINE_LOW_ONE_PIXEL indicates a single
+ * pixel solid low underline.
+ */
+ public static final Integer UNDERLINE_LOW_ONE_PIXEL = new Integer(1);
+
+ /**
+ * The Constant UNDERLINE_LOW_TWO_PIXEL indicates a double
+ * pixel solid low underline.
+ */
+ public static final Integer UNDERLINE_LOW_TWO_PIXEL = new Integer(2);
+
+ /**
+ * The Constant UNDERLINE_LOW_DOTTED indicates a
+ * single pixel dotted low underline.
+ */
+ public static final Integer UNDERLINE_LOW_DOTTED = new Integer(3);
+
+ /**
+ * The Constant UNDERLINE_LOW_GRAY indicates double pixel
+ * gray low underline.
+ */
+ public static final Integer UNDERLINE_LOW_GRAY = new Integer(4);
+
+ /**
+ * The Constant UNDERLINE_LOW_DASHED indicates single pixel dashed
+ * low underline.
+ */
+ public static final Integer UNDERLINE_LOW_DASHED = new Integer(5);
+
+ /** The WEIGHT text attribute. */
+ public static final TextAttribute WEIGHT = new TextAttribute("weight"); //$NON-NLS-1$
+
+ /**
+ * The Constant WEIGHT_EXTRA_LIGHT indicates the lightest
+ * predefined weight.
+ */
+ public static final Float WEIGHT_EXTRA_LIGHT = new Float(0.5f);
+
+ /**
+ * The Constant WEIGHT_LIGHT indicates the standard light weight.
+ */
+ public static final Float WEIGHT_LIGHT = new Float(0.75f);
+
+ /**
+ * The Constant WEIGHT_DEMILIGHT indicates an intermediate weight
+ * between LIGHT and STANDARD.
+ */
+ public static final Float WEIGHT_DEMILIGHT = new Float(0.875f);
+
+ /**
+ * The Constant WEIGHT_REGULAR indicates the standart weight.
+ */
+ public static final Float WEIGHT_REGULAR = new Float(1.0f);
+
+ /**
+ * The Constant WEIGHT_SEMIBOLD indicates a semi weight
+ * of REGULAR.
+ */
+ public static final Float WEIGHT_SEMIBOLD = new Float(1.25f);
+
+ /** The Constant WEIGHT_MEDIUM indicates average weight
+ * between the REGULAR and BOLD. */
+ public static final Float WEIGHT_MEDIUM = new Float(1.5f);
+
+ /** The Constant WEIGHT_DEMIBOLD indicates
+ * a lighter weight than BOLD. */
+ public static final Float WEIGHT_DEMIBOLD = new Float(1.75f);
+
+ /** The Constant WEIGHT_BOLD indicates the standard bold weight. */
+ public static final Float WEIGHT_BOLD = new Float(2.0f);
+
+ /** The Constant WEIGHT_HEAVY indicates a heavier weight than BOLD. */
+ public static final Float WEIGHT_HEAVY = new Float(2.25f);
+
+ /** The Constant WEIGHT_EXTRABOLD indicates an extra heavy weight. */
+ public static final Float WEIGHT_EXTRABOLD = new Float(2.5f);
+
+ /**
+ * The Constant WEIGHT_ULTRABOLD indicates the heaviest predefined
+ * weight.
+ */
+ public static final Float WEIGHT_ULTRABOLD = new Float(2.75f);
+
+ /** The WIDTH text attribute. */
+ public static final TextAttribute WIDTH = new TextAttribute("width"); //$NON-NLS-1$
+
+ /**
+ * The Constant WIDTH_CONDENSED indicates the most condensed
+ * predefined width.
+ */
+ public static final Float WIDTH_CONDENSED = new Float(0.75f);
+
+ /**
+ * The Constant WIDTH_SEMI_CONDENSED indicates
+ * a semi condensed width.
+ */
+ public static final Float WIDTH_SEMI_CONDENSED = new Float(0.875f);
+
+ /**
+ * The Constant WIDTH_REGULAR indicates the standard width.
+ */
+ public static final Float WIDTH_REGULAR = new Float(1.0f);
+
+ /**
+ * The Constant WIDTH_SEMI_EXTENDED indicates semi extended width.
+ */
+ public static final Float WIDTH_SEMI_EXTENDED = new Float(1.25f);
+
+ /**
+ * The Constant WIDTH_EXTENDED indicates extended width.
+ */
+ public static final Float WIDTH_EXTENDED = new Float(1.5f);
+
+}
diff --git a/awt-kernel/src/main/java/java/beans/IndexedPropertyChangeEvent.java b/awt-kernel/src/main/java/java/beans/IndexedPropertyChangeEvent.java
new file mode 100644
index 0000000..5bd4b2e
--- /dev/null
+++ b/awt-kernel/src/main/java/java/beans/IndexedPropertyChangeEvent.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package java.beans;
+
+/**
+ * A type of {@link PropertyChangeEvent} that indicates that an indexed property
+ * has changed.
+ *
+ * @since Android 1.0
+ */
+public class IndexedPropertyChangeEvent extends PropertyChangeEvent {
+
+ private static final long serialVersionUID = -320227448495806870L;
+
+ private final int index;
+
+ /**
+ * Creates a new property changed event with an indication of the property
+ * index.
+ *
+ * @param source
+ * the changed bean.
+ * @param propertyName
+ * the changed property, or <code>null</code> to indicate an
+ * unspecified set of the properties has changed.
+ * @param oldValue
+ * the previous value of the property, or <code>null</code> if
+ * the <code>propertyName</code> is <code>null</code> or the
+ * previous value is unknown.
+ * @param newValue
+ * the new value of the property, or <code>null</code> if the
+ * <code>propertyName</code> is <code>null</code> or the new
+ * value is unknown..
+ * @param index
+ * the index of the property.
+ */
+ public IndexedPropertyChangeEvent(Object source, String propertyName,
+ Object oldValue, Object newValue, int index) {
+ super(source, propertyName, oldValue, newValue);
+ this.index = index;
+ }
+
+ /**
+ * Answer the index of the property that was changed in this event.
+ *
+ * @return the property element index.
+ */
+ public int getIndex() {
+ return index;
+ }
+}
diff --git a/awt-kernel/src/main/java/java/beans/PropertyChangeEvent.java b/awt-kernel/src/main/java/java/beans/PropertyChangeEvent.java
new file mode 100644
index 0000000..04caed8
--- /dev/null
+++ b/awt-kernel/src/main/java/java/beans/PropertyChangeEvent.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.beans;
+
+import java.util.EventObject;
+
+/**
+ * An event that indicates that a constraint or a boundary of a property has
+ * changed.
+ *
+ * @since Android 1.0
+ */
+public class PropertyChangeEvent extends EventObject {
+
+ private static final long serialVersionUID = 7042693688939648123L;
+
+ String propertyName;
+
+ Object oldValue;
+
+ Object newValue;
+
+ Object propagationId;
+
+ /**
+ * The constructor used to create a new {@code PropertyChangeEvent}.
+ *
+ * @param source
+ * the changed bean.
+ * @param propertyName
+ * the changed property, or <code>null</code> to indicate an
+ * unspecified set of the properties has changed.
+ * @param oldValue
+ * the previous value of the property, or <code>null</code> if
+ * the <code>propertyName</code> is <code>null</code> or the
+ * previous value is unknown.
+ * @param newValue
+ * the new value of the property, or <code>null</code> if the
+ * <code>propertyName</code> is <code>null</code> or the new
+ * value is unknown.
+ */
+ public PropertyChangeEvent(Object source, String propertyName,
+ Object oldValue, Object newValue) {
+ super(source);
+
+ this.propertyName = propertyName;
+ this.oldValue = oldValue;
+ this.newValue = newValue;
+ }
+
+ /**
+ * Returns the name of the property that has changed. If an unspecified set
+ * of properties has changed it returns null.
+ *
+ * @return the name of the property that has changed, or null.
+ */
+ public String getPropertyName() {
+ return propertyName;
+ }
+
+ /**
+ * Sets the propagationId object.
+ *
+ * @see #getPropagationId()
+ */
+ public void setPropagationId(Object propagationId) {
+ this.propagationId = propagationId;
+ }
+
+ /**
+ * Returns the propagationId object. This is reserved for future use. Beans
+ * 1.0 demands that a listener receiving this property and then sending its
+ * own PropertyChangeEvent sets the received propagationId on the new
+ * PropertyChangeEvent's propagationId field.
+ *
+ * @return the propagationId object.
+ */
+ public Object getPropagationId() {
+ return propagationId;
+ }
+
+ /**
+ * Returns the old value that the property had. If the old value is unknown
+ * this method returns null.
+ *
+ * @return the old property value or null.
+ */
+ public Object getOldValue() {
+ return oldValue;
+ }
+
+ /**
+ * Returns the new value that the property now has. If the new value is
+ * unknown this method returns null.
+ *
+ * @return the old property value or null.
+ */
+ public Object getNewValue() {
+ return newValue;
+ }
+}
diff --git a/awt-kernel/src/main/java/java/beans/PropertyChangeListener.java b/awt-kernel/src/main/java/java/beans/PropertyChangeListener.java
new file mode 100644
index 0000000..2515792
--- /dev/null
+++ b/awt-kernel/src/main/java/java/beans/PropertyChangeListener.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.beans;
+
+import java.util.EventListener;
+
+/**
+ * A PropertyChangeListener can subscribe with a event source. Whenever that
+ * source raises a PropertyChangeEvent this listener will get notified.
+ *
+ * @since Android 1.0
+ */
+public interface PropertyChangeListener extends EventListener {
+
+ /**
+ * The source bean calls this method when an event is raised.
+ *
+ * @param event
+ * the {@link PropertyChangeEvent} object which contains the name
+ * and the old and new value of the property that has changed.
+ */
+ public void propertyChange(PropertyChangeEvent event);
+}
diff --git a/awt-kernel/src/main/java/java/beans/PropertyChangeListenerProxy.java b/awt-kernel/src/main/java/java/beans/PropertyChangeListenerProxy.java
new file mode 100644
index 0000000..d27e4eb
--- /dev/null
+++ b/awt-kernel/src/main/java/java/beans/PropertyChangeListenerProxy.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.beans;
+
+import java.util.EventListenerProxy;
+
+/**
+ * The implementation of this listener proxy just delegates the received events
+ * to its listener.
+ *
+ * @since Android 1.0
+ */
+public class PropertyChangeListenerProxy extends EventListenerProxy implements
+ PropertyChangeListener {
+
+ String propertyName;
+
+ /**
+ * Creates a new listener proxy that associates a listener with a property
+ * name.
+ *
+ * @param propertyName
+ * the name of the associated property.
+ * @param listener
+ * the listener to delegate incoming events to.
+ */
+ public PropertyChangeListenerProxy(String propertyName,
+ PropertyChangeListener listener) {
+ super(listener);
+ this.propertyName = propertyName;
+ }
+
+ /**
+ * Returns the name of the property associated with this listener proxy.
+ *
+ * @return the name of the associated property.
+ */
+ public String getPropertyName() {
+ return propertyName;
+ }
+
+ public void propertyChange(PropertyChangeEvent event) {
+ PropertyChangeListener listener = (PropertyChangeListener) getListener();
+ listener.propertyChange(event);
+ }
+}
diff --git a/awt-kernel/src/main/java/java/beans/PropertyChangeSupport.java b/awt-kernel/src/main/java/java/beans/PropertyChangeSupport.java
new file mode 100644
index 0000000..9225d95
--- /dev/null
+++ b/awt-kernel/src/main/java/java/beans/PropertyChangeSupport.java
@@ -0,0 +1,501 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.beans;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This utility class
+ *
+ */
+public class PropertyChangeSupport implements Serializable {
+
+ private static final long serialVersionUID = 6401253773779951803l;
+
+ private transient Object sourceBean;
+
+ private transient List<PropertyChangeListener> allPropertiesChangeListeners =
+ new ArrayList<PropertyChangeListener>();
+
+ private transient Map<String, List<PropertyChangeListener>>
+ selectedPropertiesChangeListeners =
+ new HashMap<String, List<PropertyChangeListener>>();
+
+ // fields for serialization compatibility
+ private Hashtable<String, List<PropertyChangeListener>> children;
+
+ private Object source;
+
+ private int propertyChangeSupportSerializedDataVersion = 1;
+
+ /**
+ * Creates a new instance that uses the source bean as source for any event.
+ *
+ * @param sourceBean
+ * the bean used as source for all events.
+ */
+ public PropertyChangeSupport(Object sourceBean) {
+ if (sourceBean == null) {
+ throw new NullPointerException();
+ }
+ this.sourceBean = sourceBean;
+ }
+
+ /**
+ * Fires a {@link PropertyChangeEvent} with the given name, old value and
+ * new value. As source the bean used to initialize this instance is used.
+ * If the old value and the new value are not null and equal the event will
+ * not be fired.
+ *
+ * @param propertyName
+ * the name of the property
+ * @param oldValue
+ * the old value of the property
+ * @param newValue
+ * the new value of the property
+ */
+ public void firePropertyChange(String propertyName, Object oldValue,
+ Object newValue) {
+ PropertyChangeEvent event = createPropertyChangeEvent(propertyName,
+ oldValue, newValue);
+ doFirePropertyChange(event);
+ }
+
+ /**
+ * Fires an {@link IndexedPropertyChangeEvent} with the given name, old
+ * value, new value and index. As source the bean used to initialize this
+ * instance is used. If the old value and the new value are not null and
+ * equal the event will not be fired.
+ *
+ * @param propertyName
+ * the name of the property
+ * @param index
+ * the index
+ * @param oldValue
+ * the old value of the property
+ * @param newValue
+ * the new value of the property
+ */
+ public void fireIndexedPropertyChange(String propertyName, int index,
+ Object oldValue, Object newValue) {
+
+ // nulls and equals check done in doFire...
+ doFirePropertyChange(new IndexedPropertyChangeEvent(sourceBean,
+ propertyName, oldValue, newValue, index));
+ }
+
+ /**
+ * Removes the listener from the specific property. This only happens if it
+ * was registered to this property. Nothing happens if it was not
+ * registered with this property or if the property name or the listener is
+ * null.
+ *
+ * @param propertyName
+ * the property name the listener is listening to
+ * @param listener
+ * the listener to remove
+ */
+ public synchronized void removePropertyChangeListener(String propertyName,
+ PropertyChangeListener listener) {
+ if ((propertyName != null) && (listener != null)) {
+ List<PropertyChangeListener> listeners =
+ selectedPropertiesChangeListeners.get(propertyName);
+
+ if (listeners != null) {
+ listeners.remove(listener);
+ }
+ }
+ }
+
+ /**
+ * Adds a listener to a specific property. Nothing happens if the property
+ * name or the listener is null.
+ *
+ * @param propertyName
+ * the name of the property
+ * @param listener
+ * the listener to register for the property with the given name
+ */
+ public synchronized void addPropertyChangeListener(String propertyName,
+ PropertyChangeListener listener) {
+ if ((listener != null) && (propertyName != null)) {
+ List<PropertyChangeListener> listeners =
+ selectedPropertiesChangeListeners.get(propertyName);
+
+ if (listeners == null) {
+ listeners = new ArrayList<PropertyChangeListener>();
+ selectedPropertiesChangeListeners.put(propertyName, listeners);
+ }
+
+ // RI compatibility
+ if (listener instanceof PropertyChangeListenerProxy) {
+ PropertyChangeListenerProxy proxy =
+ (PropertyChangeListenerProxy) listener;
+
+ listeners.add(new PropertyChangeListenerProxy(
+ proxy.getPropertyName(),
+ (PropertyChangeListener) proxy.getListener()));
+ } else {
+ listeners.add(listener);
+ }
+ }
+ }
+
+ /**
+ * Returns an array of listeners that registered to the property with the
+ * given name. If the property name is null an empty array is returned.
+ *
+ * @param propertyName
+ * the name of the property whose listeners should be returned
+ * @return the array of listeners to the property with the given name.
+ */
+ public synchronized PropertyChangeListener[] getPropertyChangeListeners(
+ String propertyName) {
+ List<PropertyChangeListener> listeners = null;
+
+ if (propertyName != null) {
+ listeners = selectedPropertiesChangeListeners.get(propertyName);
+ }
+
+ return (listeners == null) ? new PropertyChangeListener[] {}
+ : listeners.toArray(
+ new PropertyChangeListener[listeners.size()]);
+ }
+
+ /**
+ * Fires a property change of a boolean property with the given name. If the
+ * old value and the new value are not null and equal the event will not be
+ * fired.
+ *
+ * @param propertyName
+ * the property name
+ * @param oldValue
+ * the old value
+ * @param newValue
+ * the new value
+ */
+ public void firePropertyChange(String propertyName, boolean oldValue,
+ boolean newValue) {
+ PropertyChangeEvent event = createPropertyChangeEvent(propertyName,
+ oldValue, newValue);
+ doFirePropertyChange(event);
+ }
+
+ /**
+ * Fires a property change of a boolean property with the given name. If the
+ * old value and the new value are not null and equal the event will not be
+ * fired.
+ *
+ * @param propertyName
+ * the property name
+ * @param index
+ * the index of the changed property
+ * @param oldValue
+ * the old value
+ * @param newValue
+ * the new value
+ */
+ public void fireIndexedPropertyChange(String propertyName, int index,
+ boolean oldValue, boolean newValue) {
+
+ if (oldValue != newValue) {
+ fireIndexedPropertyChange(propertyName, index, Boolean
+ .valueOf(oldValue), Boolean.valueOf(newValue));
+ }
+ }
+
+ /**
+ * Fires a property change of an integer property with the given name. If
+ * the old value and the new value are not null and equal the event will not
+ * be fired.
+ *
+ * @param propertyName
+ * the property name
+ * @param oldValue
+ * the old value
+ * @param newValue
+ * the new value
+ */
+ public void firePropertyChange(String propertyName, int oldValue,
+ int newValue) {
+ PropertyChangeEvent event = createPropertyChangeEvent(propertyName,
+ oldValue, newValue);
+ doFirePropertyChange(event);
+ }
+
+ /**
+ * Fires a property change of an integer property with the given name. If
+ * the old value and the new value are not null and equal the event will not
+ * be fired.
+ *
+ * @param propertyName
+ * the property name
+ * @param index
+ * the index of the changed property
+ * @param oldValue
+ * the old value
+ * @param newValue
+ * the new value
+ */
+ public void fireIndexedPropertyChange(String propertyName, int index,
+ int oldValue, int newValue) {
+
+ if (oldValue != newValue) {
+ fireIndexedPropertyChange(propertyName, index,
+ new Integer(oldValue), new Integer(newValue));
+ }
+ }
+
+ /**
+ * Returns true if there are listeners registered to the property with the
+ * given name.
+ *
+ * @param propertyName
+ * the name of the property
+ * @return true if there are listeners registered to that property, false
+ * otherwise.
+ */
+ public synchronized boolean hasListeners(String propertyName) {
+ boolean result = allPropertiesChangeListeners.size() > 0;
+ if (!result && (propertyName != null)) {
+ List<PropertyChangeListener> listeners =
+ selectedPropertiesChangeListeners.get(propertyName);
+ if (listeners != null) {
+ result = listeners.size() > 0;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * removes a property change listener that was registered to all properties.
+ *
+ * @param listener
+ * the listener to remove
+ */
+ public synchronized void removePropertyChangeListener(
+ PropertyChangeListener listener) {
+ if (listener != null) {
+ if (listener instanceof PropertyChangeListenerProxy) {
+ String name = ((PropertyChangeListenerProxy) listener)
+ .getPropertyName();
+ PropertyChangeListener lst = (PropertyChangeListener)
+ ((PropertyChangeListenerProxy) listener).getListener();
+
+ removePropertyChangeListener(name, lst);
+ } else {
+ allPropertiesChangeListeners.remove(listener);
+ }
+ }
+ }
+
+ /**
+ * Registers a listener with all properties.
+ *
+ * @param listener
+ * the listener to register
+ */
+ public synchronized void addPropertyChangeListener(
+ PropertyChangeListener listener) {
+ if (listener != null) {
+ if (listener instanceof PropertyChangeListenerProxy) {
+ String name = ((PropertyChangeListenerProxy) listener)
+ .getPropertyName();
+ PropertyChangeListener lst = (PropertyChangeListener)
+ ((PropertyChangeListenerProxy) listener).getListener();
+ addPropertyChangeListener(name, lst);
+ } else {
+ allPropertiesChangeListeners.add(listener);
+ }
+ }
+ }
+
+ /**
+ * Returns an array with the listeners that registered to all properties.
+ *
+ * @return the array of listeners
+ */
+ public synchronized PropertyChangeListener[] getPropertyChangeListeners() {
+ ArrayList<PropertyChangeListener> result =
+ new ArrayList<PropertyChangeListener>(
+ allPropertiesChangeListeners);
+
+ for (String propertyName : selectedPropertiesChangeListeners.keySet()) {
+ List<PropertyChangeListener> selectedListeners =
+ selectedPropertiesChangeListeners.get(propertyName);
+
+ if (selectedListeners != null) {
+
+ for (PropertyChangeListener listener : selectedListeners) {
+ result.add(new PropertyChangeListenerProxy(propertyName,
+ listener));
+ }
+ }
+ }
+
+ return result.toArray(new PropertyChangeListener[result.size()]);
+ }
+
+ private void writeObject(ObjectOutputStream oos) throws IOException {
+ List<PropertyChangeListener> allSerializedPropertiesChangeListeners =
+ new ArrayList<PropertyChangeListener>();
+
+ for (PropertyChangeListener pcl : allPropertiesChangeListeners) {
+ if (pcl instanceof Serializable) {
+ allSerializedPropertiesChangeListeners.add(pcl);
+ }
+ }
+
+ Map<String, List<PropertyChangeListener>>
+ selectedSerializedPropertiesChangeListeners =
+ new HashMap<String, List<PropertyChangeListener>>();
+
+ for (String propertyName : selectedPropertiesChangeListeners.keySet()) {
+ List<PropertyChangeListener> keyValues =
+ selectedPropertiesChangeListeners.get(propertyName);
+
+ if (keyValues != null) {
+ List<PropertyChangeListener> serializedPropertiesChangeListeners
+ = new ArrayList<PropertyChangeListener>();
+
+ for (PropertyChangeListener pcl : keyValues) {
+ if (pcl instanceof Serializable) {
+ serializedPropertiesChangeListeners.add(pcl);
+ }
+ }
+
+ if (!serializedPropertiesChangeListeners.isEmpty()) {
+ selectedSerializedPropertiesChangeListeners.put(
+ propertyName, serializedPropertiesChangeListeners);
+ }
+ }
+ }
+
+ children = new Hashtable<String, List<PropertyChangeListener>>(
+ selectedSerializedPropertiesChangeListeners);
+ children.put("", allSerializedPropertiesChangeListeners); //$NON-NLS-1$
+ oos.writeObject(children);
+
+ Object source = null;
+ if (sourceBean instanceof Serializable) {
+ source = sourceBean;
+ }
+ oos.writeObject(source);
+
+ oos.writeInt(propertyChangeSupportSerializedDataVersion);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void readObject(ObjectInputStream ois) throws IOException,
+ ClassNotFoundException {
+ children = (Hashtable<String, List<PropertyChangeListener>>) ois
+ .readObject();
+
+ selectedPropertiesChangeListeners = new HashMap<String, List<PropertyChangeListener>>(
+ children);
+ allPropertiesChangeListeners = selectedPropertiesChangeListeners
+ .remove(""); //$NON-NLS-1$
+ if (allPropertiesChangeListeners == null) {
+ allPropertiesChangeListeners = new ArrayList<PropertyChangeListener>();
+ }
+
+ sourceBean = ois.readObject();
+ propertyChangeSupportSerializedDataVersion = ois.readInt();
+ }
+
+ /**
+ * Fires a property change event to all listeners of that property.
+ *
+ * @param event
+ * the event to fire
+ */
+ public void firePropertyChange(PropertyChangeEvent event) {
+ doFirePropertyChange(event);
+ }
+
+ private PropertyChangeEvent createPropertyChangeEvent(String propertyName,
+ Object oldValue, Object newValue) {
+ return new PropertyChangeEvent(sourceBean, propertyName, oldValue,
+ newValue);
+ }
+
+ private PropertyChangeEvent createPropertyChangeEvent(String propertyName,
+ boolean oldValue, boolean newValue) {
+ return new PropertyChangeEvent(sourceBean, propertyName, oldValue,
+ newValue);
+ }
+
+ private PropertyChangeEvent createPropertyChangeEvent(String propertyName,
+ int oldValue, int newValue) {
+ return new PropertyChangeEvent(sourceBean, propertyName, oldValue,
+ newValue);
+ }
+
+ private void doFirePropertyChange(PropertyChangeEvent event) {
+ String propertyName = event.getPropertyName();
+ Object oldValue = event.getOldValue();
+ Object newValue = event.getNewValue();
+
+ if ((newValue != null) && (oldValue != null)
+ && newValue.equals(oldValue)) {
+ return;
+ }
+
+ /*
+ * Copy the listeners collections so they can be modified while we fire
+ * events.
+ */
+
+ // Listeners to all property change events
+ PropertyChangeListener[] listensToAll;
+ // Listens to a given property change
+ PropertyChangeListener[] listensToOne = null;
+ synchronized (this) {
+ listensToAll = allPropertiesChangeListeners
+ .toArray(new PropertyChangeListener[allPropertiesChangeListeners
+ .size()]);
+
+ List<PropertyChangeListener> listeners = selectedPropertiesChangeListeners
+ .get(propertyName);
+ if (listeners != null) {
+ listensToOne = listeners
+ .toArray(new PropertyChangeListener[listeners.size()]);
+ }
+ }
+
+ // Fire the listeners
+ for (PropertyChangeListener listener : listensToAll) {
+ listener.propertyChange(event);
+ }
+ if (listensToOne != null) {
+ for (PropertyChangeListener listener : listensToOne) {
+ listener.propertyChange(event);
+ }
+ }
+ }
+
+}