001: /* Label.java
002:
003: {{IS_NOTE
004: Purpose:
005:
006: Description:
007:
008: History:
009: Wed Jun 8 18:53:53 2005, Created by tomyeh
010: }}IS_NOTE
011:
012: Copyright (C) 2005 Potix Corporation. All Rights Reserved.
013:
014: {{IS_RIGHT
015: This program is distributed under GPL Version 2.0 in the hope that
016: it will be useful, but WITHOUT ANY WARRANTY.
017: }}IS_RIGHT
018: */
019: package org.zkoss.zul;
020:
021: import java.io.Writer;
022: import java.io.IOException;
023:
024: import org.zkoss.lang.Objects;
025: import org.zkoss.xml.HTMLs;
026:
027: import org.zkoss.zk.ui.Component;
028: import org.zkoss.zk.ui.Components;
029: import org.zkoss.zk.ui.UiException;
030: import org.zkoss.zk.ui.event.Events;
031: import org.zkoss.zk.ui.metainfo.LanguageDefinition;
032:
033: import org.zkoss.zul.impl.XulElement;
034:
035: /**
036: * A label.
037: *
038: * @author tomyeh
039: */
040: public class Label extends XulElement {
041: private String _value = "";
042: private int _maxlength;
043: private boolean _pre, _hyphen, _multiline;
044:
045: public Label() {
046: }
047:
048: public Label(String value) {
049: setValue(value);
050: }
051:
052: /** Returns the value.
053: * <p>Default: "".
054: */
055: public String getValue() {
056: return _value;
057: }
058:
059: /** Sets the value.
060: */
061: public void setValue(String value) {
062: if (value == null)
063: value = "";
064: if (!Objects.equals(_value, value)) {
065: _value = value;
066: invalidate();
067: }
068: }
069:
070: /** Returns the maximal length of the label.
071: *
072: * <p>Noteice:
073: * <dl>
074: * <dt>hyphen="false" and pre="false"</dt>
075: * <dd>maxlength is the maximal length to display. Exceeding part is truncated.</dd>
076: * <dt>hyphen="true"</dt>
077: * <dd>maxlength is the maximal length of each line, and hyphenation is added
078: * if a line exceeds maxlength.</dd>
079: * <dt>hyphen="false" and pre="true"</dt>
080: * <dd>maxlength has no effect.</dd>
081: * <dt>maxlength=0</dt>
082: * <dd>hyphen has no effect</dd>
083: * </dl>
084: */
085: public int getMaxlength() {
086: return _maxlength;
087: }
088:
089: /** Sets the maximal length of the label.
090: *
091: * <p>See {@link #getMaxlength} for the relationship among pre, hyphen and
092: * maxlength.
093: */
094: public void setMaxlength(int maxlength) {
095: if (maxlength < 0)
096: maxlength = 0;
097: if (_maxlength != maxlength) {
098: _maxlength = maxlength;
099: invalidate();
100: }
101: }
102:
103: /** Returns whether to preserve the white spaces, such as space,
104: * tab and new line.
105: *
106: * <p>It is the same as style="white-space:pre". However, IE has a bug when
107: * handling such style if the content is updated dynamically.
108: * Refer to Bug 1455584.
109: *
110: * <p>See {@link #getMaxlength} for the relationship among pre, hyphen and
111: * maxlength.
112: *
113: * <p>Note: the new line is preserved either {@link #isPre} or
114: * {@link #isMultiline} returns true.
115: * In other words, <code>pre</code> implies <code>multiline</code>
116: */
117: public boolean isPre() {
118: return _pre;
119: }
120:
121: /** Sets whether to preserve the white spaces, such as space,
122: * tab and new line.
123: *
124: * <p>See {@link #getMaxlength} for the relationship among pre, hyphen and
125: * maxlength.
126: */
127: public void setPre(boolean pre) {
128: if (_pre != pre) {
129: _pre = pre;
130: invalidate();
131: }
132: }
133:
134: /** Returns whether to preserve the new line and the white spaces at the
135: * begining of each line.
136: *
137: * <p>Note: the new line is preserved either {@link #isPre} or
138: * {@link #isMultiline} returns true.
139: * In other words, <code>pre</code> implies <code>multiline</code>
140: */
141: public boolean isMultiline() {
142: return _multiline;
143: }
144:
145: /** Sets whether to preserve the new line and the white spaces at the
146: * begining of each line.
147: */
148: public void setMultiline(boolean multiline) {
149: if (_multiline != multiline) {
150: _multiline = multiline;
151: invalidate();
152: }
153: }
154:
155: /** Returns whether to hyphen a long word if maxlength is specified.
156: *
157: * <p>See {@link #getMaxlength} for the relationship among pre, hyphen and
158: * maxlength.
159: */
160: public boolean isHyphen() {
161: return _hyphen;
162: }
163:
164: /** Sets whether to hyphen a long word if maxlength is specified.
165: *
166: * <p>See {@link #getMaxlength} for the relationship among pre, hyphen and
167: * maxlength.
168: */
169: public void setHyphen(boolean hyphen) {
170: if (_hyphen != hyphen) {
171: _hyphen = hyphen;
172: invalidate();
173: }
174: }
175:
176: /** Whether to generate the value directly without ID.
177: * <p>Used only for component generated. Not for applications.
178: * @since 3.0.0
179: */
180: public boolean isIdRequired() {
181: final Component p = getParent();
182: return p == null || !isVisible() || !isRawLabel(p)
183: || !Components.isAutoId(getId())
184: || getContext() != null || getTooltip() != null
185: || getTooltiptext() != null || getPopup() != null
186: || getAction() != null || getDraggable() != null
187: || getDroppable() != null || getStyle() != null
188: || getSclass() != null || getLeft() != null
189: || getTop() != null || getWidth() != null
190: || getHeight() != null
191: || isAsapRequired(Events.ON_CLICK)
192: || isAsapRequired(Events.ON_RIGHT_CLICK)
193: || isAsapRequired(Events.ON_DOUBLE_CLICK);
194: }
195:
196: private static boolean isRawLabel(Component comp) {
197: final LanguageDefinition langdef = comp.getDefinition()
198: .getLanguageDefinition();
199: return langdef != null && langdef.isRawLabel();
200: }
201:
202: /** Returns the text for generating HTML tags (Internal Use Only).
203: *
204: * <p>Used only for component generation. Not for applications.
205: */
206: public String getEncodedText() {
207: StringBuffer sb = null;
208: final int len = _value.length();
209: if (_pre || _multiline) {
210: for (int j = 0, k;; j = k + 1) {
211: k = _value.indexOf('\n', j);
212: if (k < 0) {
213: sb = encodeLine(sb, j, len);
214: break;
215: }
216:
217: if (sb == null) {
218: assert j == 0;
219: sb = new StringBuffer(_value.length() + 10);
220: }
221: sb = encodeLine(sb, j, k > j
222: && _value.charAt(k - 1) == '\r' ? k - 1 : k);
223: sb.append("<br/>");
224: }
225: } else {
226: sb = encodeLine(null, 0, len);
227: }
228: return sb != null ? sb.toString() : _value;
229: }
230:
231: /*
232: * @param k excluded
233: */
234: private StringBuffer encodeLine(StringBuffer sb, int b, int e) {
235: boolean prews = _pre || _multiline;
236: int linesz = 0;
237: if (_maxlength > 0) {
238: int deta = e - b;
239: if (deta > _maxlength) {
240: if (_hyphen) {
241: linesz = _maxlength;
242: } else if (!prews) {
243: assert b == 0;
244: int j = _maxlength;
245: while (j > 0
246: && Character.isWhitespace(_value
247: .charAt(j - 1)))
248: --j;
249: return new StringBuffer(j + 3).append(
250: _value.substring(0, j)).append("...");
251: }
252: }
253: }
254:
255: l_linebreak: for (int cnt = 0, j = b; j < e; ++j) {
256: final char cc = _value.charAt(j);
257: String val = null;
258: if (linesz > 0 && ++cnt > linesz && j + 1 < e) {
259: sb = alloc(sb, j);
260: if (Character.isLetterOrDigit(cc)
261: && Character.isLetterOrDigit(_value
262: .charAt(j + 1))) {
263: cnt = 0;
264: for (int k = sb.length(); cnt < 3; ++cnt) {
265: if (!Character.isLetterOrDigit(sb.charAt(--k))) {
266: sb.insert(k + 1, "<br/>");
267: --j;
268: continue l_linebreak;
269: }
270: }
271: sb.append('-').append("<br/>").append(cc);
272: cnt = 1;
273: continue;
274: } else if (!Character.isWhitespace(cc)) {
275: sb.append(cc);
276: }
277: sb.append("<br/>");
278: cnt = 0;
279: continue;
280: }
281:
282: if (cc == '\t') {
283: if (prews)
284: val = " ";
285: } else if (cc == ' ' || cc == '\f') {
286: if (prews)
287: val = " ";
288: } else {
289: if (_multiline)
290: prews = false;
291:
292: switch (cc) {
293: case '<':
294: val = "<";
295: break;
296: case '>':
297: val = ">";
298: break;
299: case '&':
300: val = "&";
301: break;
302: }
303: }
304:
305: if (val != null)
306: sb = alloc(sb, j).append(val);
307: else if (sb != null)
308: sb.append(cc);
309: }
310: return sb;
311: }
312:
313: private StringBuffer alloc(StringBuffer sb, int e) {
314: if (sb == null) {
315: sb = new StringBuffer(_value.length() + 10);
316: sb.append(_value.substring(0, e));
317: }
318: return sb;
319: }
320:
321: //-- super --//
322: public String getOuterAttrs() {
323: final String attrs = super .getOuterAttrs();
324: final String clkattrs = getAllOnClickAttrs(false);
325: return clkattrs == null ? attrs : attrs + clkattrs;
326: }
327:
328: //-- Component --//
329: public void invalidate() {
330: if (isIdRequired())
331: super .invalidate();
332: else
333: getParent().invalidate();
334: }
335:
336: /** No child is allowed.
337: */
338: public boolean isChildable() {
339: return false;
340: }
341: }
|