2 * (C) Copyright IBM Corp. 1998-2008. All Rights Reserved.
\r
4 * The program is provided "as is" without any warranty express or
\r
5 * implied, including the warranty of non-infringement and the implied
\r
6 * warranties of merchantibility and fitness for a particular purpose.
\r
7 * IBM will not be liable for any damages suffered by you as a result
\r
8 * of using the Program. In no event will IBM be liable for any
\r
9 * special, indirect or consequential damages or lost profits even if
\r
10 * IBM has been advised of the possibility of their occurrence. IBM
\r
11 * will not be liable for any third party claims against you.
\r
13 package com.ibm.richtext.textpanel;
\r
15 import java.awt.Adjustable;
\r
16 import java.awt.BorderLayout;
\r
17 import java.awt.Color;
\r
18 import java.awt.Graphics;
\r
19 import java.lang.reflect.InvocationTargetException;
\r
21 import javax.swing.JPanel;
\r
22 import javax.swing.JComponent;
\r
23 import javax.swing.JScrollBar;
\r
24 import javax.swing.SwingUtilities;
\r
26 import java.awt.datatransfer.Clipboard;
\r
28 import com.ibm.richtext.textlayout.attributes.AttributeMap;
\r
30 import com.ibm.richtext.styledtext.StyleModifier;
\r
31 import com.ibm.richtext.styledtext.MConstText;
\r
34 * JTextPanel is an implementation of MTextPanel in a Swing JPanel.
\r
37 public final class JTextPanel extends JPanel implements MTextPanel {
\r
39 private static final long serialVersionUID = -675600228641043590L;
\r
41 static final String COPYRIGHT =
\r
42 "(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";
\r
43 private ATextPanelImpl fImpl;
\r
46 * Return a TextPanelSettings instance with all settings set
\r
47 * to the default values. Clients can modify this object;
\r
48 * modifications will not affect the default values.
\r
49 * @return a TextPanelSettings instance set to default values
\r
50 * @see TextPanelSettings
\r
52 public static TextPanelSettings getDefaultSettings() {
\r
54 return ATextPanelImpl.getDefaultSettings();
\r
58 * Create a new JTextPanel with the default settings.
\r
59 * @param initialText the text document. If null document text is empty.
\r
60 * @param clipboard the clipboard to use for cut, copy, and paste
\r
61 * operations. If null this panel will use a private clipboard.
\r
63 public JTextPanel(MConstText initialText,
\r
64 java.awt.datatransfer.Clipboard clipboard) {
\r
66 this(ATextPanelImpl.fgDefaultSettings, initialText, clipboard);
\r
70 * Create a new JTextPanel.
\r
71 * @param settings the settings for this JTextPanel
\r
72 * @param initialText the text document. If null document text is empty.
\r
73 * @param clipboard the clipboard to use for cut, copy, and paste
\r
74 * operations. If null this panel will use a private clipboard.
\r
75 * @see TextPanelSettings
\r
77 public JTextPanel(TextPanelSettings settings,
\r
78 MConstText initialText,
\r
79 Clipboard clipboard) {
\r
83 JScrollBar horzSb = null;
\r
84 JScrollBar vertSb = null;
\r
86 if (settings.getScrollable()) {
\r
88 setLayout(new ScrollBarLayout());
\r
90 boolean scrollBarsVisible = settings.getScrollBarsVisible();
\r
92 if (scrollBarsVisible) {
\r
93 horzSb = new JScrollBar(Adjustable.HORIZONTAL);
\r
94 vertSb = new JScrollBar(Adjustable.VERTICAL);
\r
95 add("South", horzSb);
\r
96 add("East", vertSb);
\r
100 setLayout(new BorderLayout());
\r
103 RunStrategy runStrategy = new RunStrategy() {
\r
104 void doIt(Runnable r) {
\r
106 SwingUtilities.invokeAndWait(r);
\r
108 catch(InterruptedException e) {
\r
109 // If operation was interrupted, then client
\r
110 // called wait or sleep (or something similar)
\r
111 // which is inappropriate for a client of this
\r
112 // class. Rethrow error and let client handle it.
\r
113 e.printStackTrace();
\r
114 throw new Error("Interrupted in RunStrategy: " + e);
\r
116 catch(InvocationTargetException e) {
\r
117 // Who knows how this one happens...
\r
118 e.printStackTrace();
\r
119 throw new Error("InvocationTargetException in RunStrategy: " + e);
\r
124 fImpl = new ATextPanelImpl(runStrategy,
\r
132 final FakeComponent textComponent = fImpl.getTextComponent();
\r
134 JComponent textHost = new JComponent() {
\r
136 textComponent.setHost(this);
\r
138 public void addNotify() {
\r
140 textComponent.addNotify();
\r
142 public void paint(Graphics g) {
\r
143 textComponent.paint(g);
\r
145 private static final long serialVersionUID = 1L;
\r
148 add("Center", textHost);
\r
150 textHost.requestFocus();
\r
154 * Add the given TextPanelListener to the listeners which will
\r
155 * receive update notifications from this JTextPanel.
\r
156 * @param listener the listener to add
\r
158 public void addListener(TextPanelListener listener) {
\r
160 fImpl.addListener(listener);
\r
164 * Remove the given TextPanelListener from the listeners which will
\r
165 * receive update notifications from this JTextPanel.
\r
166 * @param listener the listener to remove
\r
168 public void removeListener(TextPanelListener listener) {
\r
170 fImpl.removeListener(listener);
\r
178 * Set the document to <tt>newText</tt>. This operation
\r
179 * modifies the text in the JTextPanel. It does not modify or adopt
\r
180 * <tt>newText</tt>. This method sets the selection an insertion point at
\r
181 * the end of the text.
\r
182 * @param newText the text which will replace the current text.
\r
184 public void setText(MConstText newText) {
\r
186 fImpl.setText(newText);
\r
190 * Append the given text to the end of the document. Equivalent to
\r
191 * <tt>insert(newText, getTextLength())</tt>.
\r
192 * @param newText the text to append to the document
\r
194 public void append(MConstText newText) {
\r
196 fImpl.append(newText);
\r
200 * Insert the given text into the document at the given position.
\r
202 * <tt>replaceRange(newText, position, position)</tt>.
\r
203 * @param newText the text to insert into the document.
\r
204 * @param position the position in the document where the
\r
205 * text will be inserted
\r
207 public void insert(MConstText newText, int position) {
\r
209 fImpl.insert(newText, position);
\r
213 * Replace the given range with <tt>newText</tt>. After this
\r
214 * operation the selection range is an insertion point at the
\r
215 * end of the new text.
\r
216 * @param newText the text with which to replace the range
\r
217 * @param start the beginning of the range to replace
\r
218 * @param end the end of the range to replace
\r
220 public void replaceRange(MConstText newText, int start, int end) {
\r
222 fImpl.replaceRange(newText, start, end);
\r
226 * Return the length of the text document in the JTextPanel.
\r
227 * @return the length of the text document in the JTextPanel
\r
229 public int getTextLength() {
\r
231 return fImpl.getTextLength();
\r
235 * Return the text document in the JTextPanel.
\r
236 * @return the text document in the JTextPanel.
\r
238 public MConstText getText() {
\r
240 return fImpl.getText();
\r
244 // Selection Access
\r
248 * Return the offset of the start of the selection.
\r
250 public int getSelectionStart() {
\r
252 return fImpl.getSelectionStart();
\r
256 * Return the offset of the end of the selection.
\r
258 public int getSelectionEnd() {
\r
260 return fImpl.getSelectionEnd();
\r
264 * Set the beginning of the selection range. This is
\r
265 * equivalent to <tt>select(selectionStart, getSelectionEnd())</tt>.
\r
266 * @param selectionStart the start of the new selection range
\r
268 public void setSelectionStart(int selectionStart) {
\r
270 fImpl.setSelectionStart(selectionStart);
\r
274 * Set the end of the selection range. This is
\r
275 * equivalent to <tt>select(getSelectionStart(), selectionEnd)</tt>.
\r
276 * @param selectionEnd the end of the new selection range
\r
278 public void setSelectionEnd(int selectionEnd) {
\r
280 fImpl.setSelectionEnd(selectionEnd);
\r
284 * Set the selection range to an insertion point at the given
\r
285 * offset. This is equivalent to
\r
286 * <tt>select(position, position)</tt>.
\r
287 * @param position the offset of the new insertion point
\r
289 public void setCaretPosition(int position) {
\r
291 fImpl.setCaretPosition(position);
\r
295 * Set the selection range to the given range. The range start
\r
296 * is pinned between 0 and the text length; the range end is pinned
\r
297 * between the range start and the end of the text. These semantics
\r
298 * are identical to those of <tt>java.awt.TextComponent</tt>.
\r
299 * This method has no effect if the text is not selectable.
\r
300 * @param selectionStart the beginning of the selection range
\r
301 * @param selectionEnd the end of the selection range
\r
303 public void select(int selectionStart, int selectionEnd) {
\r
305 fImpl.select(selectionStart, selectionEnd);
\r
309 * Select all of the text in the document. This method has no effect if
\r
310 * the text is not selectable.
\r
312 public void selectAll() {
\r
323 * Return the total format width, in pixels. The format width is the
\r
324 * width to which text is wrapped.
\r
325 * @return the format width
\r
327 public int getFormatWidth() {
\r
329 return fImpl.getFormatWidth();
\r
333 * Return true if the paragraph at the given offset is left-to-right.
\r
334 * @param offset an offset in the text
\r
335 * @return true if the paragraph at the given offset is left-to-right
\r
337 public boolean paragraphIsLeftToRight(int offset) {
\r
339 return fImpl.paragraphIsLeftToRight(offset);
\r
343 * Return true if there is a change which can be undone.
\r
344 * @return true if there is a change which can be undone.
\r
346 public boolean canUndo() {
\r
348 return fImpl.canUndo();
\r
352 * Return true if there is a change which can be redone.
\r
353 * @return true if there is a change which can be redone.
\r
355 public boolean canRedo() {
\r
357 return fImpl.canRedo();
\r
361 * Return true if the clipboard contains contents which could be
\r
362 * transfered into the text.
\r
363 * @return true if the clipboard has text content.
\r
365 public boolean clipboardNotEmpty() {
\r
367 return fImpl.clipboardNotEmpty();
\r
371 * Return an AttributeMap of keys with default values. The default
\r
372 * values are used when displaying text for values which are not
\r
373 * specified in the text.
\r
374 * @return an AttributeMap of default key-value pairs
\r
376 public AttributeMap getDefaultValues() {
\r
378 return fImpl.getDefaultValues();
\r
382 * This method inspects the character style runs in the selection
\r
383 * range (or the typing style at the insertion point). It returns:
\r
385 * <li>The value of <tt>key</tt>, if the value of <tt>key</tt>
\r
386 * is the same in all of the style runs in the selection, or</li>
\r
387 * <li><tt>MULTIPLE_VALUES</tt>, if two or more style runs have different
\r
388 * values for <tt>key</tt>.</li>
\r
390 * If a style run does not contain <tt>key</tt>,
\r
391 * its value is considered to be the default style for <tt>key</tt>,
\r
392 * as defined by the default values AttributeMap. Note that if
\r
393 * <tt>key</tt> does not have a default value this method may return
\r
395 * This method is useful for configuring style menus.
\r
396 * @param key the key used to retrieve values for comparison
\r
397 * @see MTextPanel#MULTIPLE_VALUES
\r
399 public Object getCharacterStyleOverSelection(Object key) {
\r
401 return fImpl.getCharacterStyleOverSelection(key);
\r
405 * This method inspects the paragraph style runs in the selection
\r
406 * range (or the typing style at the insertion point). It returns:
\r
408 * <li>The value of <tt>key</tt>, if the value of <tt>key</tt>
\r
409 * is the same in all of the style runs in the selection, or</li>
\r
410 * <li><tt>MULTIPLE_VALUES</tt>, if two or more style runs have
\r
411 * different values for <tt>key</tt>.</li>
\r
413 * If a style run does not contain <tt>key</tt>,
\r
414 * its value is considered to be the default style for <tt>key</tt>,
\r
415 * as defined by the default values AttributeMap. Note that if
\r
416 * <tt>key</tt> does not have a default value this method may return
\r
418 * This method is useful for configuring style menus.
\r
419 * @param key the key used to retrieve values for comparison
\r
420 * @see MTextPanel#MULTIPLE_VALUES
\r
422 public Object getParagraphStyleOverSelection(Object key) {
\r
424 return fImpl.getParagraphStyleOverSelection(key);
\r
428 * Remove the selected text from the document and place it
\r
429 * on the clipboard. This method has no effect if the text
\r
430 * is not editable, or if no text is selected.
\r
432 public void cut() {
\r
437 * Place the selected text on the clipboard. This method has
\r
438 * no effect if no text is selected.
\r
440 public void copy() {
\r
445 * Replace the currently selected text with the text on the clipboard.
\r
446 * This method has no effect if the text is not editable, or if no
\r
447 * text is on the clipboard.
\r
449 public void paste() {
\r
454 * Remove selected text from the document, without altering the clipboard.
\r
455 * This method has no effect if the
\r
456 * text is not editable.
\r
458 public void clear() {
\r
463 * Undo the most recent text change. This method has no effect if
\r
464 * there is no change to undo.
\r
466 public void undo() {
\r
471 * Redo the most recent text change. This method has no effect if
\r
472 * there is no change to redo.
\r
474 public void redo() {
\r
479 * Return the number of commands the command log can hold.
\r
480 * @return the number of commands the command log can hold
\r
482 public int getCommandLogSize() {
\r
484 return fImpl.getCommandLogSize();
\r
488 * Set the number of commands the command log can hold. All
\r
489 * redoable commands are removed when this method is called.
\r
490 * @param size the number of commands kept in the command log
\r
492 public void setCommandLogSize(int size) {
\r
493 fImpl.setCommandLogSize(size);
\r
497 * Remove all commands from the command log.
\r
499 public void clearCommandLog() {
\r
500 fImpl.clearCommandLog();
\r
504 * Modify the character styles on the selected characters. If no characters
\r
505 * are selected, modify the typing style.
\r
506 * @param modifier the StyleModifier with which to modify the styles
\r
508 public void modifyCharacterStyleOnSelection(StyleModifier modifier) {
\r
509 fImpl.modifyCharacterStyleOnSelection(modifier);
\r
513 * Modify the paragraph styles in paragraphs containing selected characters, or
\r
514 * the paragraph containing the insertion point.
\r
515 * @param modifier the StyleModifier with which to modify the styles
\r
517 public void modifyParagraphStyleOnSelection(StyleModifier modifier) {
\r
518 fImpl.modifyParagraphStyleOnSelection(modifier);
\r
522 * Return the KeyRemap used to process key events.
\r
523 * @return the key remap used to process key events
\r
524 * @see #setKeyRemap
\r
526 public KeyRemap getKeyRemap() {
\r
528 return fImpl.getKeyRemap();
\r
532 * Use the given KeyRemap to map key events to characters.
\r
534 * events are affected by the remap; other text entering the
\r
535 * control (via the clipboard, for example) is not affected
\r
538 * Do not pass <tt>null</tt> to this method to leave key
\r
539 * events unmapped. Instead, use <tt>KeyRemap.getIdentityRemap()</tt>
\r
540 * @param remap the KeyRemap to use for mapping key events to characters
\r
541 * @exception java.lang.NullPointerException if parameter is null
\r
544 public void setKeyRemap(KeyRemap remap) {
\r
546 fImpl.setKeyRemap(remap);
\r
550 * Return the modification flag of the current text change.
\r
551 * @see #setModified
\r
553 public boolean isModified() {
\r
555 return fImpl.isModified();
\r
559 * Set the modification flag of the current text change.
\r
561 public void setModified(boolean modified) {
\r
563 fImpl.setModified(modified);
\r
567 * This method is for KeyEventForwarder's use only!
\r
569 ATextPanelImpl getImpl() {
\r
574 public void setBackground(Color color) {
\r
575 super.setBackground (color);
\r
576 java.awt.Component[] compList = getComponents();
\r
577 for (int i = 0; i < compList.length; i++) {
\r
578 if (!(compList[i] instanceof JScrollBar)) {
\r
579 compList[i].setBackground (color);
\r