(empty log message)
@@ -1,17 +1,15 @@ | ||
1 | 1 | package org.phosphoresce.lib.swing; |
2 | 2 | |
3 | -import java.awt.Color; | |
4 | -import java.awt.Dimension; | |
5 | -import java.awt.Rectangle; | |
3 | +import java.awt.Graphics; | |
6 | 4 | |
7 | 5 | import javax.accessibility.Accessible; |
8 | 6 | import javax.swing.JComponent; |
9 | 7 | import javax.swing.JLabel; |
8 | +import javax.swing.JPanel; | |
10 | 9 | import javax.swing.JTextField; |
11 | 10 | import javax.swing.SwingConstants; |
12 | -import javax.swing.border.CompoundBorder; | |
11 | +import javax.swing.SwingUtilities; | |
13 | 12 | import javax.swing.border.EmptyBorder; |
14 | -import javax.swing.border.MatteBorder; | |
15 | 13 | import javax.swing.text.JTextComponent; |
16 | 14 | |
17 | 15 | /** |
@@ -29,95 +27,144 @@ | ||
29 | 27 | */ |
30 | 28 | public class JLabelField extends JComponent implements SwingConstants, Accessible { |
31 | 29 | |
30 | + /** ディフォルトキャプションギャップ */ | |
31 | + public final int DEFAULT_CAPTION_GAP = 5; | |
32 | + | |
33 | + /** ディフォルトキャプション区切り文字 */ | |
34 | + public final String DEFAULT_CAPTION_SEPARATOR = ":"; | |
35 | + | |
36 | + /** キャプション */ | |
37 | + private String caption; | |
38 | + | |
39 | + /** キャプションギャップ */ | |
40 | + private int captionGap; | |
41 | + | |
42 | + /** キャプション区切り文字 */ | |
43 | + private String captionSeparator; | |
44 | + | |
45 | + /** キャプション幅 */ | |
46 | + private Integer captionWidth; | |
47 | + | |
48 | + /** キャプション横方向配置位置 */ | |
49 | + private int captionHorizontalAlignment; | |
50 | + | |
51 | + /** キャプション縦方向配置位置 */ | |
52 | + private int captionVerticalAlignment; | |
53 | + | |
54 | + /** 自動フィールド高さ調整 */ | |
55 | + private boolean autoHeight; | |
56 | + | |
57 | + /** フィールドコンポーネント */ | |
58 | + private JComponent fieldComponent; | |
59 | + | |
60 | + /** バックグラウンドパネル */ | |
61 | + private JPanel backgroundPanel; | |
62 | + | |
32 | 63 | /** キャプションラベル */ |
33 | 64 | private JLabel captionLabel; |
34 | 65 | |
35 | - /** カスタムフィールド */ | |
36 | - private JTextComponent field; | |
37 | - | |
38 | - /** ディフォルトフィールド */ | |
66 | + /** ディフォルトフィールドコンポーネント */ | |
39 | 67 | private JTextField defaultField; |
40 | 68 | |
41 | - /** キャプションラベルギャップ */ | |
42 | - private int labelGap; | |
43 | - | |
44 | - /** キャプションラベル幅 */ | |
45 | - private Integer labelWidth; | |
46 | - | |
47 | 69 | /** |
48 | 70 | * コンストラクタ<br> |
49 | 71 | */ |
50 | 72 | public JLabelField() { |
51 | 73 | super(); |
52 | - setLayout(null); | |
53 | - setBorder(new EmptyBorder(5, 5, 5, 5)); | |
54 | - add(getCaptionLabel()); | |
55 | - add(getDefaultField()); | |
56 | - setBounds(0, 0, 128, 32); | |
57 | - setLabelWidth(null); | |
58 | - setLabelGap(5); | |
59 | - updateLayout(); | |
74 | + this.caption = null; | |
75 | + this.captionGap = DEFAULT_CAPTION_GAP; | |
76 | + this.captionSeparator = DEFAULT_CAPTION_SEPARATOR; | |
77 | + this.captionWidth = null; | |
78 | + this.captionHorizontalAlignment = SwingUtilities.LEFT; | |
79 | + this.captionVerticalAlignment = SwingUtilities.CENTER; | |
80 | + this.autoHeight = false; | |
81 | + this.fieldComponent = null; | |
82 | + add(getBackgroundPanel()); | |
83 | + //add(getCaptionLabel()); | |
84 | + //add(getDefaultField()); | |
85 | + setOpaque(false); | |
86 | + setBorder(new EmptyBorder(3, 3, 3, 3)); | |
60 | 87 | } |
61 | 88 | |
62 | 89 | /** |
63 | - * このコンポーネントを移動し、サイズ変更します。<br> | |
64 | - * 左上隅の新しい位置は x および y によって指定され、新しいサイズは width および height によって指定されます。<br> | |
65 | - * @param x このコンポーネントの新しい x 座標 | |
66 | - * @param y このコンポーネントの新しい y 座標 | |
67 | - * @param width このコンポーネントの新しい width | |
68 | - * @param height このコンポーネントの新しい height | |
69 | - * @see java.awt.Component#setBounds(int, int, int, int) | |
90 | + * @see javax.swing.JComponent#updateUI() | |
70 | 91 | */ |
71 | - public void setBounds(int x, int y, int width, int height) { | |
72 | - super.setBounds(x, y, width, height); | |
73 | - updateLayout(); | |
92 | + @Override | |
93 | + public void updateUI() { | |
94 | + getBackgroundPanel().updateUI(); | |
95 | + getCaptionLabel().updateUI(); | |
96 | + getDefaultField().updateUI(); | |
97 | + getFieldComponent().updateUI(); | |
74 | 98 | } |
75 | 99 | |
76 | 100 | /** |
77 | - * 新しい境界の矩形 r に適合するようにこのコンポーネントを移動し、サイズ変更します。<br> | |
78 | - * このコンポーネントの新しい位置は r.x および r.y によって指定され、新しいサイズは r.width および r.height によって指定されます。<br> | |
79 | - * @param r このコンポーネントの新しい境界の矩形 | |
80 | - * @see java.awt.Component#setBounds(java.awt.Rectangle) | |
101 | + * @see javax.swing.JComponent#paintComponent(java.awt.Graphics) | |
81 | 102 | */ |
82 | 103 | @Override |
83 | - public void setBounds(Rectangle r) { | |
84 | - super.setBounds(r); | |
104 | + protected void paintComponent(Graphics g) { | |
85 | 105 | updateLayout(); |
106 | + super.paintComponent(g); | |
86 | 107 | } |
87 | 108 | |
88 | 109 | /** |
89 | - * フィールドテキストを取得します。<br> | |
90 | - * @return フィールドテキスト | |
110 | + * レイアウトを更新します。<br> | |
91 | 111 | */ |
92 | - public String getText() { | |
93 | - return getField().getText(); | |
112 | + private void updateLayout() { | |
113 | + updateLayoutOfBackground(); | |
114 | + updateLayoutOfLabel(); | |
115 | + updateLayoutOfField(); | |
116 | + updateProperties(); | |
94 | 117 | } |
95 | 118 | |
96 | 119 | /** |
97 | - * フィールドテキストを設定します。<br> | |
98 | - * @param text フィールドテキスト | |
120 | + * プロパティ設定を子コンポーネントに反映します。<br> | |
99 | 121 | */ |
100 | - public void setText(String text) { | |
101 | - getField().setText(text); | |
122 | + private void updateProperties() { | |
123 | + JComponent[] components = new JComponent[] { // | |
124 | + // | |
125 | + getBackgroundPanel(), // | |
126 | + getDefaultField(), // | |
127 | + getFieldComponent(), // | |
128 | + getCaptionLabel(), // | |
129 | + }; | |
130 | + for (JComponent component : components) { | |
131 | + component.setEnabled(isEnabled()); | |
132 | + component.setFont(getFont()); | |
133 | + component.setForeground(getForeground()); | |
134 | + if (!(component instanceof JTextComponent)) { | |
135 | + component.setOpaque(isOpaque()); | |
136 | + } | |
137 | + } | |
102 | 138 | } |
103 | 139 | |
104 | 140 | /** |
105 | - * レイアウトを更新します。<br> | |
141 | + * バックグラウンド部レイアウトを更新します。<rb> | |
106 | 142 | */ |
107 | - private void updateLayout() { | |
108 | - updateLayoutOfLabel(); | |
109 | - updateLayoutOfField(); | |
110 | - updatePreferredSize(); | |
143 | + private void updateLayoutOfBackground() { | |
144 | + int iHeight = getInsets().top + getInsets().bottom; | |
145 | + int iWidth = getInsets().left + getInsets().right; | |
146 | + int x = getInsets().left; | |
147 | + int y = getInsets().top; | |
148 | + int width = getBounds().width - iWidth; | |
149 | + int height = autoHeight ? getFieldComponent().getPreferredSize().height + iHeight : getBounds().height - iHeight; | |
150 | + getBackgroundPanel().setBounds(x, y, width, height); | |
151 | + if (autoHeight) { | |
152 | + setBounds(getBounds().x, getBounds().y, getBounds().width, height); | |
153 | + } | |
111 | 154 | } |
112 | 155 | |
113 | 156 | /** |
114 | - * ラベル部レイアウトを更新します。<rb> | |
157 | + * キャプション部レイアウトを更新します。<rb> | |
115 | 158 | */ |
116 | 159 | private void updateLayoutOfLabel() { |
117 | - int x = getInsets().left; | |
118 | - int y = getInsets().top; | |
119 | - int width = labelWidth != null ? labelWidth : captionLabel.getPreferredSize().width; | |
120 | - int height = getPreferredSize().height - (getInsets().top + getInsets().bottom); | |
160 | + //int x = getInsets().left; | |
161 | + //int y = getInsets().top; | |
162 | + //int width = captionWidth != null ? captionWidth : captionLabel.getPreferredSize().width; | |
163 | + //int height = preferredHeight ? getFieldComponent().getPreferredSize().height : getBounds().height - (getInsets().top + getInsets().bottom); | |
164 | + int x = 0; | |
165 | + int y = 0; | |
166 | + int width = captionWidth != null ? captionWidth : captionLabel.getPreferredSize().width; | |
167 | + int height = autoHeight ? getFieldComponent().getPreferredSize().height : getBackgroundPanel().getBounds().height; | |
121 | 168 | getCaptionLabel().setBounds(x, y, width, height); |
122 | 169 | } |
123 | 170 |
@@ -125,111 +172,205 @@ | ||
125 | 172 | * フィールド部レイアウトを更新します。<br> |
126 | 173 | */ |
127 | 174 | private void updateLayoutOfField() { |
128 | - int x = getInsets().left + getCaptionLabel().getBounds().width + labelGap; | |
129 | - int y = getInsets().top; | |
130 | - int width = getPreferredSize().width - (getInsets().left + getInsets().right + getCaptionLabel().getBounds().width + labelGap); | |
131 | - int height = getPreferredSize().height - (getInsets().top + getInsets().bottom); | |
132 | - getField().setBounds(x, y, width, height); | |
175 | + //int x = getInsets().left + getCaptionLabel().getBounds().width + captionGap; | |
176 | + //int y = getInsets().top; | |
177 | + //int width = getBounds().width - (getInsets().left + getInsets().right + getCaptionLabel().getBounds().width + captionGap); | |
178 | + //int height = preferredHeight ? getFieldComponent().getPreferredSize().height : getBounds().height - (getInsets().top + getInsets().bottom); | |
179 | + int x = getCaptionLabel().getBounds().width + captionGap; | |
180 | + int y = 0; | |
181 | + int width = getBackgroundPanel().getBounds().width - (getCaptionLabel().getBounds().width + captionGap); | |
182 | + int height = autoHeight ? getFieldComponent().getPreferredSize().height : getBackgroundPanel().getBounds().height; | |
183 | + getFieldComponent().setBounds(x, y, width, height); | |
133 | 184 | } |
134 | 185 | |
135 | 186 | /** |
136 | - * コンポーネントサイズを更新します。<br> | |
187 | + * キャプションを取得します。<br> | |
188 | + * @return キャプション | |
137 | 189 | */ |
138 | - private void updatePreferredSize() { | |
139 | - Dimension dimension = super.getPreferredSize(); | |
140 | - dimension.width = getCaptionLabel().getPreferredSize().width + getField().getPreferredSize().width + getInsets().left + getInsets().right + labelGap; | |
141 | - dimension.height = getCaptionLabel().getPreferredSize().height + getInsets().top + getInsets().bottom; | |
190 | + public String getCaption() { | |
191 | + return caption; | |
142 | 192 | } |
143 | 193 | |
144 | 194 | /** |
145 | - * キャプションを設定します。 | |
195 | + * キャプションを設定します。<br> | |
146 | 196 | * @param caption キャプション |
147 | 197 | */ |
148 | 198 | public void setCaption(String caption) { |
149 | - getCaptionLabel().setText(caption); | |
199 | + String old = this.caption; | |
200 | + this.caption = caption; | |
201 | + firePropertyChange("caption", old, caption); | |
202 | + getCaptionLabel().setText(caption + (captionSeparator == null || captionSeparator.length() <= 0 ? "" : captionSeparator)); | |
150 | 203 | } |
151 | 204 | |
152 | 205 | /** |
153 | - * キャプションラベルを取得します。 | |
154 | - * @return キャプションラベル | |
206 | + * キャプションギャップを取得します。<br> | |
207 | + * @return キャプションギャップ | |
155 | 208 | */ |
156 | - private JLabel getCaptionLabel() { | |
157 | - if (captionLabel == null) { | |
158 | - captionLabel = new JLabel("Caption"); | |
159 | - captionLabel.setBorder(new CompoundBorder(new MatteBorder(0, 3, 0, 0, (Color) new Color(0, 102, 204)), new EmptyBorder(0, 3, 0, 0))); | |
160 | - captionLabel.setHorizontalAlignment(JLabel.LEFT); | |
161 | - captionLabel.setVerticalAlignment(JLabel.CENTER); | |
162 | - } | |
163 | - return captionLabel; | |
209 | + public int getCaptionGap() { | |
210 | + return captionGap; | |
164 | 211 | } |
165 | 212 | |
166 | 213 | /** |
167 | - * カスタムフィールドを取得します。 | |
168 | - * @return カスタムフィールド | |
214 | + * キャプションギャップを設定します。<br> | |
215 | + * @param labelGap キャプションギャップ | |
169 | 216 | */ |
170 | - private JTextComponent getField() { | |
171 | - if (field == null) { | |
172 | - return getDefaultField(); | |
173 | - } | |
174 | - return field; | |
217 | + public void setCaptionGap(int labelGap) { | |
218 | + int old = this.captionGap; | |
219 | + this.captionGap = labelGap; | |
220 | + firePropertyChange("labelGap", old, labelGap); | |
175 | 221 | } |
176 | 222 | |
177 | 223 | /** |
178 | - * カスタムフィールドを設定します。 | |
179 | - * @param field カスタムフィールド | |
224 | + * キャプション区切り文字を取得します。<br> | |
225 | + * @return キャプション区切り文字 | |
180 | 226 | */ |
181 | - public void setField(JTextComponent field) { | |
182 | - if (getField().equals(field)) { | |
183 | - return; | |
184 | - } | |
185 | - remove(getField()); | |
186 | - this.field = field; | |
187 | - add(getField()); | |
188 | - updateLayout(); | |
227 | + public String getCaptionSeparator() { | |
228 | + return captionSeparator; | |
189 | 229 | } |
190 | 230 | |
191 | 231 | /** |
192 | - * ディフォルトフィールドを取得します。 | |
193 | - * @return ディフォルトフィールド | |
232 | + * キャプション区切り文字を設定します。<br> | |
233 | + * @param captionDivision キャプション区切り文字 | |
194 | 234 | */ |
195 | - private JTextField getDefaultField() { | |
196 | - if (defaultField == null) { | |
197 | - defaultField = new JTextField("Field"); | |
235 | + public void setCaptionSeparator(String captionDivision) { | |
236 | + this.captionSeparator = captionDivision; | |
237 | + } | |
238 | + | |
239 | + /** | |
240 | + * キャプション幅を取得します。<br> | |
241 | + * @return キャプション幅 | |
242 | + */ | |
243 | + public Integer getCaptionWidth() { | |
244 | + return captionWidth; | |
245 | + } | |
246 | + | |
247 | + /** | |
248 | + * キャプション幅を設定します。<br> | |
249 | + * @param labelWidth キャプション幅 | |
250 | + */ | |
251 | + public void setCaptionWidth(Integer labelWidth) { | |
252 | + Integer old = this.captionWidth; | |
253 | + this.captionWidth = labelWidth; | |
254 | + firePropertyChange("labelWidth", old, labelWidth); | |
255 | + } | |
256 | + | |
257 | + /** | |
258 | + * キャプション横方向配置位置を取得します。<br> | |
259 | + * @return キャプション横方向配置位置 | |
260 | + */ | |
261 | + public int getCaptionHorizontalAlignment() { | |
262 | + return captionHorizontalAlignment; | |
263 | + } | |
264 | + | |
265 | + /** | |
266 | + * キャプション横方向配置位置を設定します。<br> | |
267 | + * @param captionHorizontalAlignment キャプション横方向配置位置 | |
268 | + */ | |
269 | + public void setCaptionHorizontalAlignment(int captionHorizontalAlignment) { | |
270 | + int old = this.captionHorizontalAlignment; | |
271 | + this.captionHorizontalAlignment = captionHorizontalAlignment; | |
272 | + firePropertyChange("captionHorizontalAlignment", old, captionHorizontalAlignment); | |
273 | + getCaptionLabel().setHorizontalAlignment(captionHorizontalAlignment); | |
274 | + } | |
275 | + | |
276 | + /** | |
277 | + * キャプション縦方向配置位置を取得します。<br> | |
278 | + * @return キャプション縦方向配置位置 | |
279 | + */ | |
280 | + public int getCaptionVerticalAlignment() { | |
281 | + return captionVerticalAlignment; | |
282 | + } | |
283 | + | |
284 | + /** | |
285 | + * キャプション縦方向配置位置を設定します。<br> | |
286 | + * @param captionVerticalAlignment キャプション縦方向配置位置 | |
287 | + */ | |
288 | + public void setCaptionVerticalAlignment(int captionVerticalAlignment) { | |
289 | + int old = this.captionVerticalAlignment; | |
290 | + this.captionVerticalAlignment = captionVerticalAlignment; | |
291 | + firePropertyChange("captionVerticalAlignment", old, captionVerticalAlignment); | |
292 | + getCaptionLabel().setVerticalAlignment(captionVerticalAlignment); | |
293 | + } | |
294 | + | |
295 | + /** | |
296 | + * 自動フィールド高さ調整を取得します。<br> | |
297 | + * @return 自動フィールド高さ調整 | |
298 | + */ | |
299 | + public boolean isAutoHeight() { | |
300 | + return autoHeight; | |
301 | + } | |
302 | + | |
303 | + /** | |
304 | + * 自動フィールド高さ調整を設定します。<br> | |
305 | + * @param preferredHeight 自動フィールド高さ調整 | |
306 | + */ | |
307 | + public void setAutoHeight(boolean preferredHeight) { | |
308 | + boolean old = this.autoHeight; | |
309 | + this.autoHeight = preferredHeight; | |
310 | + firePropertyChange("preferredHeight", old, captionVerticalAlignment); | |
311 | + } | |
312 | + | |
313 | + /** | |
314 | + * バックグラウンドパネルを取得します。<br> | |
315 | + * @return バックグラウンドパネル | |
316 | + */ | |
317 | + private JPanel getBackgroundPanel() { | |
318 | + if (backgroundPanel == null) { | |
319 | + backgroundPanel = new JPanel(); | |
320 | + backgroundPanel.setLayout(null); | |
321 | + backgroundPanel.add(getCaptionLabel()); | |
322 | + backgroundPanel.add(getDefaultField()); | |
198 | 323 | } |
199 | - return defaultField; | |
324 | + return backgroundPanel; | |
200 | 325 | } |
201 | 326 | |
202 | 327 | /** |
203 | - * キャプションラベルギャップを設定します。 | |
204 | - * @param labelSpace キャプションラベルギャップ | |
328 | + * フィールドコンポーネントを取得します。<br> | |
329 | + * @return フィールドコンポーネント | |
205 | 330 | */ |
206 | - public void setLabelGap(int labelSpace) { | |
207 | - this.labelGap = labelSpace; | |
208 | - updateLayout(); | |
331 | + private JComponent getFieldComponent() { | |
332 | + if (fieldComponent == null) { | |
333 | + return getDefaultField(); | |
334 | + } | |
335 | + return fieldComponent; | |
209 | 336 | } |
210 | 337 | |
211 | 338 | /** |
212 | - * キャプションラベルギャップを取得します。 | |
213 | - * @return キャプションラベルギャップ | |
339 | + * フィールドコンポーネントを設定します。<br> | |
340 | + * @param field フィールドコンポーネント | |
214 | 341 | */ |
215 | - public int getLabelGap() { | |
216 | - return labelGap; | |
342 | + public void setFieldComponent(JComponent field) { | |
343 | + if (getFieldComponent().equals(field)) { | |
344 | + return; | |
345 | + } | |
346 | + //remove(getFieldComponent()); | |
347 | + getBackgroundPanel().remove(getFieldComponent()); | |
348 | + JComponent old = this.fieldComponent; | |
349 | + this.fieldComponent = field; | |
350 | + firePropertyChange("field", old, field); | |
351 | + //add(getFieldComponent()); | |
352 | + getBackgroundPanel().add(getFieldComponent()); | |
217 | 353 | } |
218 | 354 | |
219 | 355 | /** |
220 | - * キャプションラベル幅を取得します。 | |
221 | - * @return キャプションラベル幅 | |
356 | + * キャプションラベルを取得します。<br> | |
357 | + * @return キャプションラベル | |
222 | 358 | */ |
223 | - public Integer getLabelWidth() { | |
224 | - return labelWidth; | |
359 | + private JLabel getCaptionLabel() { | |
360 | + if (captionLabel == null) { | |
361 | + captionLabel = new JLabel(); | |
362 | + } | |
363 | + return captionLabel; | |
225 | 364 | } |
226 | 365 | |
227 | 366 | /** |
228 | - * キャプションラベル幅を設定します。 | |
229 | - * @param labelWidth キャプションラベル幅 | |
367 | + * ディフォルトフィールドコンポーネントを取得します。<br> | |
368 | + * @return ディフォルトフィールドコンポーネント | |
230 | 369 | */ |
231 | - public void setLabelWidth(Integer labelWidth) { | |
232 | - this.labelWidth = labelWidth; | |
233 | - updateLayout(); | |
370 | + private JTextField getDefaultField() { | |
371 | + if (defaultField == null) { | |
372 | + defaultField = new JTextField(); | |
373 | + } | |
374 | + return defaultField; | |
234 | 375 | } |
235 | 376 | } |