001: /*
002: * (C) Copyright IBM Corp. 1998-2004. All Rights Reserved.
003: *
004: * The program is provided "as is" without any warranty express or
005: * implied, including the warranty of non-infringement and the implied
006: * warranties of merchantibility and fitness for a particular purpose.
007: * IBM will not be liable for any damages suffered by you as a result
008: * of using the Program. In no event will IBM be liable for any
009: * special, indirect or consequential damages or lost profits even if
010: * IBM has been advised of the possibility of their occurrence. IBM
011: * will not be liable for any third party claims against you.
012: */
013: package com.ibm.richtext.textpanel;
014:
015: import java.awt.BorderLayout;
016: import java.awt.Component;
017: import java.awt.Graphics;
018: import java.awt.Panel;
019: import java.awt.Scrollbar;
020:
021: import java.awt.datatransfer.Clipboard;
022:
023: import com.ibm.richtext.textlayout.attributes.AttributeMap;
024:
025: import com.ibm.richtext.styledtext.StyleModifier;
026: import com.ibm.richtext.styledtext.MConstText;
027:
028: /**
029: * TextPanel is an implementation of MTextPanel in an AWT Panel.
030: * @see MTextPanel
031: */
032: public final class TextPanel extends Panel implements MTextPanel {
033:
034: private ATextPanelImpl fImpl;
035:
036: /**
037: * Return a TextPanelSettings instance with all settings set
038: * to the default values. Clients can modify this object;
039: * modifications will not affect the default values.
040: * @return a TextPanelSettings instance set to default values
041: * @see TextPanelSettings
042: */
043: public static TextPanelSettings getDefaultSettings() {
044:
045: return ATextPanelImpl.getDefaultSettings();
046: }
047:
048: /**
049: * Create a new TextPanel with the default settings.
050: * @param initialText the text document. If null document text is empty.
051: * @param clipboard the clipboard to use for cut, copy, and paste
052: * operations. If null this panel will use a private clipboard.
053: */
054: public TextPanel(MConstText initialText, Clipboard clipboard) {
055:
056: this (ATextPanelImpl.fgDefaultSettings, initialText, clipboard);
057: }
058:
059: /**
060: * Create a new TextPanel.
061: * @param settings the settings for this TextPanel
062: * @param initialText the text document. If null document text is empty.
063: * @param clipboard the clipboard to use for cut, copy, and paste
064: * operations. If null this panel will use a private clipboard.
065: * @see TextPanelSettings
066: */
067: public TextPanel(TextPanelSettings settings,
068: MConstText initialText, Clipboard clipboard) {
069:
070: Scrollbar horzSb = null;
071: Scrollbar vertSb = null;
072:
073: if (settings.getScrollable()) {
074:
075: setLayout(new ScrollBarLayout());
076:
077: boolean scrollBarsVisible = settings.getScrollBarsVisible();
078:
079: if (scrollBarsVisible) {
080: horzSb = new Scrollbar(Scrollbar.HORIZONTAL);
081: vertSb = new Scrollbar(Scrollbar.VERTICAL);
082: add("South", horzSb);
083: add("East", vertSb);
084: }
085: } else {
086: setLayout(new BorderLayout());
087: }
088:
089: fImpl = new ATextPanelImpl(new RunStrategy(), settings,
090: initialText, clipboard, this , horzSb, vertSb);
091:
092: final FakeComponent textComponent = fImpl.getTextComponent();
093:
094: Component textHost = new Component() {
095: {
096: textComponent.setHost(this );
097: }
098:
099: public void addNotify() {
100: super .addNotify();
101: textComponent.addNotify();
102: }
103:
104: public void paint(Graphics g) {
105: textComponent.paint(g);
106: }
107: };
108:
109: add("Center", textHost);
110:
111: textHost.requestFocus();
112: }
113:
114: /**
115: * Add the given TextPanelListener to the listeners which will
116: * receive update notifications from this TextPanel.
117: * @param listener the listener to add
118: */
119: public void addListener(TextPanelListener listener) {
120:
121: fImpl.addListener(listener);
122: }
123:
124: /**
125: * Remove the given TextPanelListener from the listeners which will
126: * receive update notifications from this TextPanel.
127: * @param listener the listener to remove
128: */
129: public void removeListener(TextPanelListener listener) {
130:
131: fImpl.removeListener(listener);
132: }
133:
134: //============
135: // Text Access
136: //============
137:
138: /**
139: * Set the document to <tt>newText</tt>. This operation
140: * modifies the text in the TextPanel. It does not modify or adopt
141: * <tt>newText</tt>. This method sets the selection an insertion point at
142: * the end of the text.
143: * @param newText the text which will replace the current text.
144: */
145: public void setText(MConstText newText) {
146:
147: fImpl.setText(newText);
148: }
149:
150: /**
151: * Append the given text to the end of the document. Equivalent to
152: * <tt>insert(newText, getTextLength())</tt>.
153: * @param newText the text to append to the document
154: */
155: public void append(MConstText newText) {
156:
157: fImpl.append(newText);
158: }
159:
160: /**
161: * Insert the given text into the document at the given position.
162: * Equivalent to
163: * <tt>replaceRange(newText, position, position)</tt>.
164: * @param newText the text to insert into the document.
165: * @param position the position in the document where the
166: * text will be inserted
167: */
168: public void insert(MConstText newText, int position) {
169:
170: fImpl.insert(newText, position);
171: }
172:
173: /**
174: * Replace the given range with <tt>newText</tt>. After this
175: * operation the selection range is an insertion point at the
176: * end of the new text.
177: * @param newText the text with which to replace the range
178: * @param start the beginning of the range to replace
179: * @param end the end of the range to replace
180: */
181: public void replaceRange(MConstText newText, int start, int end) {
182:
183: fImpl.replaceRange(newText, start, end);
184: }
185:
186: /**
187: * Return the length of the text document in the TextPanel.
188: * @return the length of the text document in the TextPanel
189: */
190: public int getTextLength() {
191:
192: return fImpl.getTextLength();
193: }
194:
195: /**
196: * Return the text document in the TextPanel.
197: * @return the text document in the TextPanel.
198: */
199: public MConstText getText() {
200:
201: return fImpl.getText();
202: }
203:
204: //============
205: // Selection Access
206: //============
207:
208: /**
209: * Return the offset of the start of the selection.
210: */
211: public int getSelectionStart() {
212:
213: return fImpl.getSelectionStart();
214: }
215:
216: /**
217: * Return the offset of the end of the selection.
218: */
219: public int getSelectionEnd() {
220:
221: return fImpl.getSelectionEnd();
222: }
223:
224: /**
225: * Set the beginning of the selection range. This is
226: * equivalent to <tt>select(selectionStart, getSelectionEnd())</tt>.
227: * @param selectionStart the start of the new selection range
228: */
229: public void setSelectionStart(int selectionStart) {
230:
231: fImpl.setSelectionStart(selectionStart);
232: }
233:
234: /**
235: * Set the end of the selection range. This is
236: * equivalent to <tt>select(getSelectionStart(), selectionEnd)</tt>.
237: * @param selectionEnd the end of the new selection range
238: */
239: public void setSelectionEnd(int selectionEnd) {
240:
241: fImpl.setSelectionEnd(selectionEnd);
242: }
243:
244: /**
245: * Set the selection range to an insertion point at the given
246: * offset. This is equivalent to
247: * <tt>select(position, position)</tt>.
248: * @param position the offset of the new insertion point
249: */
250: public void setCaretPosition(int position) {
251:
252: fImpl.setCaretPosition(position);
253: }
254:
255: /**
256: * Set the selection range to the given range. The range start
257: * is pinned between 0 and the text length; the range end is pinned
258: * between the range start and the end of the text. These semantics
259: * are identical to those of <tt>java.awt.TextComponent</tt>.
260: * This method has no effect if the text is not selectable.
261: * @param selectionStart the beginning of the selection range
262: * @param selectionEnd the end of the selection range
263: */
264: public void select(int selectionStart, int selectionEnd) {
265:
266: fImpl.select(selectionStart, selectionEnd);
267: }
268:
269: /**
270: * Select all of the text in the document. This method has no effect if
271: * the text is not selectable.
272: */
273: public void selectAll() {
274:
275: fImpl.selectAll();
276: }
277:
278: //============
279: // Format Width
280: //============
281:
282: /**
283: * Return the total format width, in pixels. The format width is the
284: * width to which text is wrapped.
285: * @return the format width
286: */
287: public int getFormatWidth() {
288:
289: return fImpl.getFormatWidth();
290: }
291:
292: /**
293: * Return true if the paragraph at the given offset is left-to-right.
294: * @param offset an offset in the text
295: * @return true if the paragraph at the given offset is left-to-right
296: */
297: public boolean paragraphIsLeftToRight(int offset) {
298:
299: return fImpl.paragraphIsLeftToRight(offset);
300: }
301:
302: /**
303: * Return true if there is a change which can be undone.
304: * @return true if there is a change which can be undone.
305: */
306: public boolean canUndo() {
307:
308: return fImpl.canUndo();
309: }
310:
311: /**
312: * Return true if there is a change which can be redone.
313: * @return true if there is a change which can be redone.
314: */
315: public boolean canRedo() {
316:
317: return fImpl.canRedo();
318: }
319:
320: /**
321: * Return true if the clipboard contains contents which could be
322: * transfered into the text.
323: * @return true if the clipboard has text content.
324: */
325: public boolean clipboardNotEmpty() {
326:
327: return fImpl.clipboardNotEmpty();
328: }
329:
330: /**
331: * Return an AttributeMap of keys with default values. The default
332: * values are used when displaying text for values which are not
333: * specified in the text.
334: * @return an AttributeMap of default key-value pairs
335: */
336: public AttributeMap getDefaultValues() {
337:
338: return fImpl.getDefaultValues();
339: }
340:
341: /**
342: * This method inspects the character style runs in the selection
343: * range (or the typing style at the insertion point). It returns:
344: * <ul>
345: * <li>The value of <tt>key</tt>, if the value of <tt>key</tt>
346: * is the same in all of the style runs in the selection, or</li>
347: * <li><tt>MULTIPLE_VALUES</tt>, if two or more style runs have different
348: * values for <tt>key</tt>.</li>
349: * </ul>
350: * If a style run does not contain <tt>key</tt>,
351: * its value is considered to be the default style for <tt>key</tt>,
352: * as defined by the default values AttributeMap. Note that if
353: * <tt>key</tt> does not have a default value this method may return
354: * null.
355: * This method is useful for configuring style menus.
356: * @param key the key used to retrieve values for comparison
357: * @see MTextPanel#MULTIPLE_VALUES
358: */
359: public Object getCharacterStyleOverSelection(Object key) {
360:
361: return fImpl.getCharacterStyleOverSelection(key);
362: }
363:
364: /**
365: * This method inspects the paragraph style runs in the selection
366: * range (or the typing style at the insertion point). It returns:
367: * <ul>
368: * <li>The value of <tt>key</tt>, if the value of <tt>key</tt>
369: * is the same in all of the style runs in the selection, or</li>
370: * <li><tt>MULTIPLE_VALUES</tt>, if two or more style runs have
371: * different values for <tt>key</tt>.</li>
372: * </ul>
373: * If a style run does not contain <tt>key</tt>,
374: * its value is considered to be the default style for <tt>key</tt>,
375: * as defined by the default values AttributeMap. Note that if
376: * <tt>key</tt> does not have a default value this method may return
377: * null.
378: * This method is useful for configuring style menus.
379: * @param key the key used to retrieve values for comparison
380: * @see MTextPanel#MULTIPLE_VALUES
381: */
382: public Object getParagraphStyleOverSelection(Object key) {
383:
384: return fImpl.getParagraphStyleOverSelection(key);
385: }
386:
387: /**
388: * Remove the selected text from the document and place it
389: * on the clipboard. This method has no effect if the text
390: * is not editable, or if no text is selected.
391: */
392: public void cut() {
393: fImpl.cut();
394: }
395:
396: /**
397: * Place the selected text on the clipboard. This method has
398: * no effect if no text is selected.
399: */
400: public void copy() {
401: fImpl.copy();
402: }
403:
404: /**
405: * Replace the currently selected text with the text on the clipboard.
406: * This method has no effect if the text is not editable, or if no
407: * text is on the clipboard.
408: */
409: public void paste() {
410: fImpl.paste();
411: }
412:
413: /**
414: * Remove selected text from the document, without altering the clipboard.
415: * This method has no effect if the
416: * text is not editable.
417: */
418: public void clear() {
419: fImpl.clear();
420: }
421:
422: /**
423: * Undo the most recent text change. This method has no effect if
424: * there is no change to undo.
425: */
426: public void undo() {
427: fImpl.undo();
428: }
429:
430: /**
431: * Redo the most recent text change. This method has no effect if
432: * there is no change to redo.
433: */
434: public void redo() {
435: fImpl.redo();
436: }
437:
438: /**
439: * Return the number of commands the command log can hold.
440: * @return the number of commands the command log can hold
441: */
442: public int getCommandLogSize() {
443:
444: return fImpl.getCommandLogSize();
445: }
446:
447: /**
448: * Set the number of commands the command log can hold. All
449: * redoable commands are removed when this method is called.
450: * @param size the number of commands kept in the command log
451: */
452: public void setCommandLogSize(int size) {
453: fImpl.setCommandLogSize(size);
454: }
455:
456: /**
457: * Remove all commands from the command log.
458: */
459: public void clearCommandLog() {
460: fImpl.clearCommandLog();
461: }
462:
463: /**
464: * Modify the character styles on the selected characters. If no characters
465: * are selected, modify the typing style.
466: * @param modifier the StyleModifier with which to modify the styles
467: */
468: public void modifyCharacterStyleOnSelection(StyleModifier modifier) {
469: fImpl.modifyCharacterStyleOnSelection(modifier);
470: }
471:
472: /**
473: * Modify the paragraph styles in paragraphs containing selected characters, or
474: * the paragraph containing the insertion point.
475: * @param modifier the StyleModifier with which to modify the styles
476: */
477: public void modifyParagraphStyleOnSelection(StyleModifier modifier) {
478: fImpl.modifyParagraphStyleOnSelection(modifier);
479: }
480:
481: /**
482: * Return the KeyRemap used to process key events.
483: * @return the key remap used to process key events
484: * @see #setKeyRemap
485: */
486: public KeyRemap getKeyRemap() {
487:
488: return fImpl.getKeyRemap();
489: }
490:
491: /**
492: * Use the given KeyRemap to map key events to characters.
493: * Only key
494: * events are affected by the remap; other text entering the
495: * control (via the clipboard, for example) is not affected
496: * by the KeyRemap.
497: * <p>
498: * Do not pass <tt>null</tt> to this method to leave key
499: * events unmapped. Instead, use <tt>KeyRemap.getIdentityRemap()</tt>
500: * @param remap the KeyRemap to use for mapping key events to characters
501: * @exception java.lang.NullPointerException if parameter is null
502: * @see KeyRemap
503: */
504: public void setKeyRemap(KeyRemap remap) {
505:
506: fImpl.setKeyRemap(remap);
507: }
508:
509: /**
510: * Return the modification flag of the current text change.
511: * @see #setModified
512: */
513: public boolean isModified() {
514:
515: return fImpl.isModified();
516: }
517:
518: /**
519: * Set the modification flag of the current text change.
520: */
521: public void setModified(boolean modified) {
522:
523: fImpl.setModified(modified);
524: }
525:
526: /**
527: * This method is for KeyEventForwarder's use only!
528: */
529: ATextPanelImpl getImpl() {
530:
531: return fImpl;
532: }
533: }
|