LEFT | RIGHT |
1 // © 2017 and later: Unicode, Inc. and others. | 1 // © 2017 and later: Unicode, Inc. and others. |
2 // License & terms of use: http://www.unicode.org/copyright.html#License | 2 // License & terms of use: http://www.unicode.org/copyright.html#License |
3 package com.ibm.icu.impl.number.formatters; | 3 package com.ibm.icu.impl.number.formatters; |
4 | 4 |
5 import com.ibm.icu.impl.number.Format.AfterFormat; | 5 import com.ibm.icu.impl.number.Format.AfterFormat; |
6 import com.ibm.icu.impl.number.ModifierHolder; | 6 import com.ibm.icu.impl.number.ModifierHolder; |
7 import com.ibm.icu.impl.number.NumberStringBuilder; | 7 import com.ibm.icu.impl.number.NumberStringBuilder; |
8 import com.ibm.icu.impl.number.Properties; | 8 import com.ibm.icu.impl.number.Properties; |
9 | 9 |
10 public class PaddingFormat implements AfterFormat { | 10 public class PaddingFormat implements AfterFormat { |
11 public enum PaddingLocation { | 11 public enum PadPosition { |
12 BEFORE_PREFIX, | 12 BEFORE_PREFIX, |
13 AFTER_PREFIX, | 13 AFTER_PREFIX, |
14 BEFORE_SUFFIX, | 14 BEFORE_SUFFIX, |
15 AFTER_SUFFIX; | 15 AFTER_SUFFIX; |
16 | 16 |
17 public static PaddingLocation fromOld(int old) { | 17 public static PadPosition fromOld(int old) { |
18 switch (old) { | 18 switch (old) { |
19 case com.ibm.icu.text.DecimalFormat.PAD_BEFORE_PREFIX: | 19 case com.ibm.icu.text.DecimalFormat.PAD_BEFORE_PREFIX: |
20 return PaddingLocation.BEFORE_PREFIX; | 20 return PadPosition.BEFORE_PREFIX; |
21 case com.ibm.icu.text.DecimalFormat.PAD_AFTER_PREFIX: | 21 case com.ibm.icu.text.DecimalFormat.PAD_AFTER_PREFIX: |
22 return PaddingLocation.AFTER_PREFIX; | 22 return PadPosition.AFTER_PREFIX; |
23 case com.ibm.icu.text.DecimalFormat.PAD_BEFORE_SUFFIX: | 23 case com.ibm.icu.text.DecimalFormat.PAD_BEFORE_SUFFIX: |
24 return PaddingLocation.BEFORE_SUFFIX; | 24 return PadPosition.BEFORE_SUFFIX; |
25 case com.ibm.icu.text.DecimalFormat.PAD_AFTER_SUFFIX: | 25 case com.ibm.icu.text.DecimalFormat.PAD_AFTER_SUFFIX: |
26 return PaddingLocation.AFTER_SUFFIX; | 26 return PadPosition.AFTER_SUFFIX; |
27 default: | 27 default: |
28 throw new IllegalArgumentException("Don't know how to map " + old); | 28 throw new IllegalArgumentException("Don't know how to map " + old); |
29 } | 29 } |
30 } | 30 } |
31 | 31 |
32 public int toOld() { | 32 public int toOld() { |
33 switch (this) { | 33 switch (this) { |
34 case BEFORE_PREFIX: | 34 case BEFORE_PREFIX: |
35 return com.ibm.icu.text.DecimalFormat.PAD_BEFORE_PREFIX; | 35 return com.ibm.icu.text.DecimalFormat.PAD_BEFORE_PREFIX; |
36 case AFTER_PREFIX: | 36 case AFTER_PREFIX: |
37 return com.ibm.icu.text.DecimalFormat.PAD_AFTER_PREFIX; | 37 return com.ibm.icu.text.DecimalFormat.PAD_AFTER_PREFIX; |
38 case BEFORE_SUFFIX: | 38 case BEFORE_SUFFIX: |
39 return com.ibm.icu.text.DecimalFormat.PAD_BEFORE_SUFFIX; | 39 return com.ibm.icu.text.DecimalFormat.PAD_BEFORE_SUFFIX; |
40 case AFTER_SUFFIX: | 40 case AFTER_SUFFIX: |
41 return com.ibm.icu.text.DecimalFormat.PAD_AFTER_SUFFIX; | 41 return com.ibm.icu.text.DecimalFormat.PAD_AFTER_SUFFIX; |
42 default: | 42 default: |
43 return -1; // silence compiler errors | 43 return -1; // silence compiler errors |
44 } | 44 } |
45 } | 45 } |
46 } | 46 } |
47 | 47 |
48 public static interface IProperties { | 48 public static interface IProperties { |
49 | 49 |
50 static int DEFAULT_PADDING_WIDTH = 0; | 50 static int DEFAULT_FORMAT_WIDTH = 0; |
51 | 51 |
52 /** @see #setPaddingWidth */ | 52 /** @see #setFormatWidth */ |
53 public int getPaddingWidth(); | 53 public int getFormatWidth(); |
54 | 54 |
55 /** | 55 /** |
56 * Sets the minimum width of the string output by the formatting pipeline. F
or example, if | 56 * Sets the minimum width of the string output by the formatting pipeline. F
or example, if |
57 * padding is enabled and paddingWidth is set to 6, formatting the number "3
.14159" with the | 57 * padding is enabled and paddingWidth is set to 6, formatting the number "3
.14159" with the |
58 * pattern "0.00" will result in "··3.14" if '·' is your padding string. | 58 * pattern "0.00" will result in "··3.14" if '·' is your padding string. |
59 * | 59 * |
60 * <p>If the number is longer than your padding width, the number will displ
ay as if no padding | 60 * <p>If the number is longer than your padding width, the number will displ
ay as if no padding |
61 * width had been specified, which may result in strings longer than the pad
ding width. | 61 * width had been specified, which may result in strings longer than the pad
ding width. |
62 * | 62 * |
63 * <p>Width is counted in UTF-16 code units. | 63 * <p>Width is counted in UTF-16 code units. |
64 * | 64 * |
65 * @param paddingWidth The output width. | 65 * @param formatWidth The output width. |
66 * @return The property bag, for chaining. | 66 * @return The property bag, for chaining. |
67 * @see #setPaddingString | 67 * @see #setPadPosition |
68 * @see #setPaddingLocation | 68 * @see #setPadString |
69 */ | 69 */ |
70 public IProperties setPaddingWidth(int paddingWidth); | 70 public IProperties setFormatWidth(int formatWidth); |
71 | 71 |
72 static String DEFAULT_PADDING_STRING = null; | 72 static String DEFAULT_PAD_STRING = null; |
73 | 73 |
74 /** @see #setPaddingString */ | 74 /** @see #setPadString */ |
75 public String getPaddingString(); | 75 public String getPadString(); |
76 | 76 |
77 /** | 77 /** |
78 * Sets the string used for padding. This can be any string, but it usually
makes sense for it | 78 * Sets the string used for padding. The string should contain a single char
acter or grapheme |
79 * to be a single character or code point long. | 79 * cluster. |
80 * | 80 * |
81 * <p>If you do not pass a String object, the CharSequence will be converted
to a String upon | 81 * <p>Must be used in conjunction with {@link #setFormatWidth}. |
82 * construction of the formatting pipeline object. | |
83 * | |
84 * <p>Must be used in conjunction with {@link #setPaddingWidth}. | |
85 * | 82 * |
86 * @param paddingString The padding string. Defaults to an ASCII space (U+00
20). | 83 * @param paddingString The padding string. Defaults to an ASCII space (U+00
20). |
87 * @return The property bag, for chaining. | 84 * @return The property bag, for chaining. |
88 * @see #setPaddingWidth | 85 * @see #setFormatWidth |
89 */ | 86 */ |
90 public IProperties setPaddingString(String paddingString); | 87 public IProperties setPadString(String paddingString); |
91 | 88 |
92 static PaddingLocation DEFAULT_PADDING_LOCATION = null; | 89 static PadPosition DEFAULT_PAD_POSITION = null; |
93 | 90 |
94 /** @see #setPaddingLocation */ | 91 /** @see #setPadPosition */ |
95 public PaddingLocation getPaddingLocation(); | 92 public PadPosition getPadPosition(); |
96 | 93 |
97 /** | 94 /** |
98 * Sets the location where the padding string is to be inserted to maintain
the padding width: | 95 * Sets the location where the padding string is to be inserted to maintain
the padding width: |
99 * one of BEFORE_PREFIX, AFTER_PREFIX, BEFORE_SUFFIX, or AFTER_SUFFIX. | 96 * one of BEFORE_PREFIX, AFTER_PREFIX, BEFORE_SUFFIX, or AFTER_SUFFIX. |
100 * | 97 * |
101 * <p>Must be used in conjunction with {@link #setPaddingWidth}. | 98 * <p>Must be used in conjunction with {@link #setFormatWidth}. |
102 * | 99 * |
103 * @param paddingLocation The output width. | 100 * @param padPosition The output width. |
104 * @return The property bag, for chaining. | 101 * @return The property bag, for chaining. |
105 * @see #setPaddingWidth | 102 * @see #setFormatWidth |
106 */ | 103 */ |
107 public IProperties setPaddingLocation(PaddingLocation paddingLocation); | 104 public IProperties setPadPosition(PadPosition padPosition); |
108 } | 105 } |
109 | 106 |
110 public static final String FALLBACK_PADDING_STRING = "\u0020"; // i.e. a space | 107 public static final String FALLBACK_PADDING_STRING = "\u0020"; // i.e. a space |
111 | 108 |
112 public static boolean usePadding(IProperties properties) { | 109 public static boolean usePadding(IProperties properties) { |
113 return properties.getPaddingWidth() != IProperties.DEFAULT_PADDING_WIDTH; | 110 return properties.getFormatWidth() != IProperties.DEFAULT_FORMAT_WIDTH; |
114 } | 111 } |
115 | 112 |
116 public static AfterFormat getInstance(IProperties properties) { | 113 public static AfterFormat getInstance(IProperties properties) { |
117 return new PaddingFormat( | 114 return new PaddingFormat( |
118 properties.getPaddingWidth(), | 115 properties.getFormatWidth(), |
119 properties.getPaddingString(), | 116 properties.getPadString(), |
120 properties.getPaddingLocation()); | 117 properties.getPadPosition()); |
121 } | 118 } |
122 | 119 |
123 // Properties | 120 // Properties |
124 private final int paddingWidth; | 121 private final int paddingWidth; |
125 private final String paddingString; | 122 private final String paddingString; |
126 private final PaddingLocation paddingLocation; | 123 private final PadPosition paddingLocation; |
127 | 124 |
128 private PaddingFormat( | 125 private PaddingFormat( |
129 int paddingWidth, String paddingString, PaddingLocation paddingLocation) { | 126 int paddingWidth, String paddingString, PadPosition paddingLocation) { |
130 this.paddingWidth = paddingWidth > 0 ? paddingWidth : 10; // TODO: Is this a
sensible default? | 127 this.paddingWidth = paddingWidth > 0 ? paddingWidth : 10; // TODO: Is this a
sensible default? |
131 this.paddingString = paddingString != null ? paddingString : FALLBACK_PADDIN
G_STRING; | 128 this.paddingString = paddingString != null ? paddingString : FALLBACK_PADDIN
G_STRING; |
132 this.paddingLocation = | 129 this.paddingLocation = |
133 paddingLocation != null ? paddingLocation : PaddingLocation.BEFORE_PREFI
X; | 130 paddingLocation != null ? paddingLocation : PadPosition.BEFORE_PREFIX; |
134 } | 131 } |
135 | 132 |
136 @Override | 133 @Override |
137 public int after(ModifierHolder mods, NumberStringBuilder string, int leftInde
x, int rightIndex) { | 134 public int after(ModifierHolder mods, NumberStringBuilder string, int leftInde
x, int rightIndex) { |
138 | 135 |
139 // TODO: Count code points instead of code units? | 136 // TODO: Count code points instead of code units? |
140 int requiredPadding = paddingWidth - (rightIndex - leftIndex) - mods.totalLe
ngth(); | 137 int requiredPadding = paddingWidth - (rightIndex - leftIndex) - mods.totalLe
ngth(); |
141 | 138 |
142 if (requiredPadding <= 0) { | 139 if (requiredPadding <= 0) { |
143 // Skip padding, but still apply modifiers to be consistent | 140 // Skip padding, but still apply modifiers to be consistent |
144 return mods.applyAll(string, leftIndex, rightIndex); | 141 return mods.applyAll(string, leftIndex, rightIndex); |
145 } | 142 } |
146 | 143 |
147 int length = 0; | 144 int length = 0; |
148 if (paddingLocation == PaddingLocation.AFTER_PREFIX) { | 145 if (paddingLocation == PadPosition.AFTER_PREFIX) { |
149 length += addPadding(requiredPadding, string, leftIndex); | 146 length += addPadding(requiredPadding, string, leftIndex); |
150 } else if (paddingLocation == PaddingLocation.BEFORE_SUFFIX) { | 147 } else if (paddingLocation == PadPosition.BEFORE_SUFFIX) { |
151 length += addPadding(requiredPadding, string, rightIndex); | 148 length += addPadding(requiredPadding, string, rightIndex); |
152 } | 149 } |
153 length += mods.applyAll(string, leftIndex, rightIndex + length); | 150 length += mods.applyAll(string, leftIndex, rightIndex + length); |
154 if (paddingLocation == PaddingLocation.BEFORE_PREFIX) { | 151 if (paddingLocation == PadPosition.BEFORE_PREFIX) { |
155 length += addPadding(requiredPadding, string, leftIndex); | 152 length += addPadding(requiredPadding, string, leftIndex); |
156 } else if (paddingLocation == PaddingLocation.AFTER_SUFFIX) { | 153 } else if (paddingLocation == PadPosition.AFTER_SUFFIX) { |
157 length += addPadding(requiredPadding, string, rightIndex + length); | 154 length += addPadding(requiredPadding, string, rightIndex + length); |
158 } | 155 } |
159 | 156 |
160 return length; | 157 return length; |
161 } | 158 } |
162 | 159 |
163 private int addPadding(int requiredPadding, NumberStringBuilder string, int in
dex) { | 160 private int addPadding(int requiredPadding, NumberStringBuilder string, int in
dex) { |
164 for (int i = 0; i < requiredPadding; i++) { | 161 for (int i = 0; i < requiredPadding; i++) { |
165 string.insert(index, paddingString, null); | 162 string.insert(index, paddingString, null); |
166 } | 163 } |
167 return paddingString.length() * requiredPadding; | 164 return paddingString.length() * requiredPadding; |
168 } | 165 } |
169 | 166 |
170 @Override | 167 @Override |
171 public void export(Properties properties) { | 168 public void export(Properties properties) { |
172 properties.setPaddingWidth(paddingWidth); | 169 properties.setFormatWidth(paddingWidth); |
173 properties.setPaddingString(paddingString); | 170 properties.setPadString(paddingString); |
174 properties.setPaddingLocation(paddingLocation); | 171 properties.setPadPosition(paddingLocation); |
175 } | 172 } |
176 } | 173 } |
LEFT | RIGHT |