001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Evgeniya G. Maenkova
019: * @version $Revision$
020: */package javax.swing;
021:
022: import java.awt.Dimension;
023: import java.awt.Font;
024: import java.awt.FontMetrics;
025: import java.awt.Rectangle;
026: import javax.accessibility.AccessibleContext;
027: import javax.accessibility.AccessibleState;
028: import javax.accessibility.AccessibleStateSet;
029: import javax.swing.text.AbstractDocument;
030: import javax.swing.text.BadLocationException;
031: import javax.swing.text.Document;
032: import javax.swing.text.JTextComponent;
033: import javax.swing.text.PlainDocument;
034:
035: import org.apache.harmony.x.swing.StringConstants;
036:
037: import org.apache.harmony.x.swing.internal.nls.Messages;
038:
039: public class JTextArea extends JTextComponent {
040: protected class AccessibleJTextArea extends
041: JTextComponent.AccessibleJTextComponent {
042: /**
043: * Adds state AccessibleState.MULTI_LINE to super class states
044: */
045: public AccessibleStateSet getAccessibleStateSet() {
046: AccessibleStateSet ass = super .getAccessibleStateSet();
047: ass.add(AccessibleState.MULTI_LINE);
048: return ass;
049: }
050: }
051:
052: private static final String uiClassID = "TextAreaUI";
053:
054: private int rows;
055:
056: private int columns;
057:
058: private boolean wrapWord;
059:
060: private boolean wrapLine;
061:
062: private int rowHeight;
063:
064: private int columnsWidth;
065:
066: private Integer tabSize;
067:
068: public JTextArea(final Document doc, final String s, final int r,
069: final int c) {
070: super ();
071: if (r < 0) {
072: throw new IllegalArgumentException(Messages.getString(
073: "swing.3C", r)); //$NON-NLS-1$
074: }
075: if (c < 0) {
076: throw new IllegalArgumentException(Messages.getString(
077: "swing.3D", c)); //$NON-NLS-1$
078: }
079: Document document = doc;
080: if (document == null) {
081: document = createDefaultModel();
082: }
083: setDocument(document);
084: if (s != null) {
085: try {
086: document.remove(0, document.getLength());
087: document.insertString(0, s, null);
088: } catch (final BadLocationException e) {
089: }
090: }
091: rows = r;
092: columns = c;
093: evaluate(getFont());
094: tabSize = (Integer) document.getProperty("tabSize");
095: }
096:
097: public JTextArea(final Document doc) {
098: this (doc, null, 0, 0);
099: }
100:
101: public JTextArea(final String s, final int r, final int c) {
102: this (null, s, r, c);
103: }
104:
105: public JTextArea(final String s) {
106: this (null, s, 0, 0);
107: }
108:
109: public JTextArea(final int r, final int c) {
110: this (null, null, r, c);
111: }
112:
113: public JTextArea() {
114: this (null, null, 0, 0);
115: }
116:
117: public synchronized void append(final String s) {
118: Document doc = getDocument();
119: if (doc == null || (s == null || s == "")) {
120: return;
121: }
122: try {
123: doc.insertString(doc.getLength(), s, null);
124: } catch (final BadLocationException e) {
125: }
126: }
127:
128: private int checkLineCount(final int line)
129: throws BadLocationException {
130: int count = getDocument().getDefaultRootElement()
131: .getElementCount();
132: if (line < 0) {
133: throw new BadLocationException(Messages
134: .getString("swing.3E"), line); //$NON-NLS-1$
135: }
136: if (line >= count) {
137: throw new BadLocationException(Messages
138: .getString("swing.3F"), line); //$NON-NLS-1$
139: }
140: return count;
141: }
142:
143: protected Document createDefaultModel() {
144: return new PlainDocument();
145: }
146:
147: /*
148: * Sets new columnsWidth and rowHeight
149: */
150: private void evaluate(final Font f) {
151: if (f != null) {
152: FontMetrics fm = getFontMetrics(f);
153: rowHeight = fm.getHeight();
154: columnsWidth = fm.charWidth('m');
155: } else {
156: rowHeight = 0;
157: columnsWidth = 0;
158: }
159: }
160:
161: public AccessibleContext getAccessibleContext() {
162: if (accessibleContext == null) {
163: accessibleContext = new AccessibleJTextArea();
164: }
165: return accessibleContext;
166: }
167:
168: public int getColumns() {
169: return columns;
170: }
171:
172: protected int getColumnWidth() {
173: return columnsWidth;
174: }
175:
176: public int getLineCount() {
177: Document doc = getDocument();
178: int count = 0;
179: readLock(doc);
180: try {
181: count = doc.getDefaultRootElement().getElementCount();
182: } finally {
183: readUnlock(doc);
184: }
185: return count;
186: }
187:
188: public int getLineEndOffset(final int line)
189: throws BadLocationException {
190: Document doc = getDocument();
191: int end = doc.getLength();
192: int count = 0;
193: readLock(doc);
194: try {
195: count = checkLineCount(line);
196: end = doc.getDefaultRootElement().getElement(line)
197: .getEndOffset();
198: } finally {
199: readUnlock(doc);
200: }
201: return (line == count - 1) ? end - 1 : end;
202: }
203:
204: public int getLineOfOffset(final int offset)
205: throws BadLocationException {
206: Document doc = getDocument();
207: int length = doc.getLength();
208: if (offset < 0 || offset > length) {
209: throw new BadLocationException(Messages
210: .getString("swing.40"), //$NON-NLS-1$
211: offset);
212: }
213: readLock(doc);
214: int index = 0;
215: try {
216: index = doc.getDefaultRootElement().getElementIndex(offset);
217: } finally {
218: readUnlock(doc);
219: }
220: return index;
221: }
222:
223: public int getLineStartOffset(final int line)
224: throws BadLocationException {
225: Document doc = getDocument();
226: readLock(doc);
227: int start = 0;
228: try {
229: checkLineCount(line);
230: start = doc.getDefaultRootElement().getElement(line)
231: .getStartOffset();
232: } finally {
233: readUnlock(doc);
234: }
235: return start;
236: }
237:
238: public boolean getLineWrap() {
239: return wrapLine;
240: }
241:
242: public Dimension getPreferredScrollableViewportSize() {
243: Dimension dim = getPreferredSize();
244: int width = (columns == 0) ? dim.width : columns * columnsWidth;
245: int height = (rows == 0) ? dim.height : rows * rowHeight;
246: return new Dimension(width, height);
247: }
248:
249: public Dimension getPreferredSize() {
250: int width1 = columns * columnsWidth;
251: int height1 = rows * rowHeight;
252: Dimension dim2 = super .getPreferredSize();
253: int width2 = dim2.width;
254: int height2 = dim2.height;
255: return new Dimension(Math.max(width1, width2), Math.max(
256: height1, height2));
257: }
258:
259: protected int getRowHeight() {
260: return rowHeight;
261: }
262:
263: public int getRows() {
264: return rows;
265: }
266:
267: public boolean getScrollableTracksViewportWidth() {
268: return super .getScrollableTracksViewportWidth() || wrapLine;
269: }
270:
271: public int getScrollableUnitIncrement(final Rectangle r,
272: final int orientation, final int direction) {
273: if (orientation == SwingConstants.HORIZONTAL) {
274: return columnsWidth;
275: }
276: if (orientation == SwingConstants.VERTICAL) {
277: return rowHeight;
278: }
279: throw new IllegalArgumentException(Messages.getString(
280: "swing.41", orientation)); //$NON-NLS-1$
281: }
282:
283: public int getTabSize() {
284: return tabSize.intValue();
285: }
286:
287: public String getUIClassID() {
288: return uiClassID;
289: }
290:
291: public boolean getWrapStyleWord() {
292: return wrapWord;
293: }
294:
295: public synchronized void insert(final String s, final int pos) {
296: Document doc = getDocument();
297: if (doc == null || (s == null || s == "")) {
298: return;
299: }
300: int length = doc.getLength();
301: if (pos < 0 || pos > length) {
302: throw new IllegalArgumentException(Messages
303: .getString("swing.42")); //$NON-NLS-1$
304: }
305: try {
306: doc.insertString(pos, s, null);
307: } catch (final BadLocationException e) {
308: }
309:
310: }
311:
312: /*
313: * The format of the string is based on 1.5 release behavior
314: * which can be revealed using the following code:
315: *
316: * Object obj = new JTextArea();
317: * System.out.println(obj.toString());
318: */
319: protected String paramString() {
320: return super .paramString() + "," + "columns=" + getColumns()
321: + "," + "columnWidth=" + getColumnWidth() + ","
322: + "rows=" + getRows() + "," + "rowHeight="
323: + getRowHeight() + "," + "word=" + getWrapStyleWord()
324: + "," + "wrap=" + getLineWrap();
325: }
326:
327: private void readLock(final Document doc) {
328: if (!(doc instanceof AbstractDocument)) {
329: return;
330: }
331: ((AbstractDocument) doc).readLock();
332: }
333:
334: private void readUnlock(final Document doc) {
335: if (!(doc instanceof AbstractDocument)) {
336: return;
337: }
338: ((AbstractDocument) doc).readUnlock();
339: }
340:
341: public synchronized void replaceRange(final String s,
342: final int start, final int end) {
343: Document doc = getDocument();
344: if (doc == null) {
345: return;
346: }
347: int length = doc.getLength();
348: if (start < 0 || end > length) {
349: throw new IllegalArgumentException(Messages
350: .getString("swing.43")); //$NON-NLS-1$
351: }
352: if (start > end) {
353: throw new IllegalArgumentException(Messages
354: .getString("swing.44")); //$NON-NLS-1$
355: }
356:
357: try {
358: doc.remove(start, end - start);
359: if (s != null && s != "") {
360: doc.insertString(start, s, null);
361: }
362: } catch (final BadLocationException e) {
363: }
364: }
365:
366: public void setColumns(final int c) {
367: if (c < 0) {
368: throw new IllegalArgumentException(Messages
369: .getString("swing.45")); //$NON-NLS-1$
370: }
371: columns = c;
372: invalidate();
373: }
374:
375: public void setFont(final Font f) {
376: super .setFont(f);
377: evaluate(f);
378: revalidate();
379: //Perhaps JComponent should do it
380: repaint();
381: }
382:
383: public void setLineWrap(final boolean b) {
384: boolean old = wrapLine;
385: wrapLine = b;
386: firePropertyChange(
387: StringConstants.TEXT_COMPONENT_LINE_WRAP_PROPERTY, old,
388: b);
389: }
390:
391: public void setRows(final int r) {
392: if (r < 0) {
393: throw new IllegalArgumentException(Messages
394: .getString("swing.46")); //$NON-NLS-1$
395: }
396: rows = r;
397: invalidate();
398: }
399:
400: /**
401: * Sets document's property PlainDocument.tabSizeAttribute.
402: */
403: public void setTabSize(final int size) {
404: Integer old = tabSize;
405: tabSize = new Integer(size);
406: Document doc = getDocument();
407: if (doc != null) {
408: doc.putProperty(PlainDocument.tabSizeAttribute, tabSize);
409: }
410: firePropertyChange(PlainDocument.tabSizeAttribute, old, tabSize);
411: }
412:
413: public void setWrapStyleWord(final boolean b) {
414: boolean old = wrapWord;
415: wrapWord = b;
416: firePropertyChange(
417: StringConstants.TEXT_COMPONENT_WRAP_STYLE_WORD_PROPERTY,
418: old, b);
419: }
420: }
|