*/ private void invokeAction(String name, Action altAction) { ActionMap map = getActionMap(); Action action = null; if (map != null) { action = map.get(name); } if (action == null) { installDefaultTransferHandlerIfNecessary(); action = altAction; } action.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, (String)action. getValue(Action.NAME), EventQueue.getMostRecentEventTime(), getCurrentEventModifiers())); } /** * If the current <code>TransferHandler</code> is null, this will * install a new one. */ private void installDefaultTransferHandlerIfNecessary() { if (getTransferHandler() == null) { if (defaultTransferHandler == null) { defaultTransferHandler = new DefaultTransferHandler(); } setTransferHandler(defaultTransferHandler); } } /** * Moves the caret to a new position, leaving behind a mark * defined by the last time <code>setCaretPosition</code> was * called. This forms a selection. * If the document is <code>null</code>, does nothing. The position * must be between 0 and the length of the component's text or else * an exception is thrown. * * @param pos the position * @exception IllegalArgumentException if the value supplied * for <code>position</code> is less than zero or greater * than the component's text length * @see #setCaretPosition */ public void moveCaretPosition(int pos) { Document doc = getDocument(); if (doc != null) { if (pos > doc.getLength() || pos < 0) { throw new IllegalArgumentException("bad position: " + pos); } caret.moveDot(pos); } } /** * The bound property name for the focus accelerator. */ public static final String FOCUS_ACCELERATOR_KEY = "focusAcceleratorKey"; /** * Sets the key accelerator that will cause the receiving text * component to get the focus. The accelerator will be the * key combination of the <em>alt</em> key and the character * given (converted to upper case). By default, there is no focus * accelerator key. Any previous key accelerator setting will be * superseded. A '\0' key setting will be registered, and has the * effect of turning off the focus accelerator. When the new key * is set, a PropertyChange event (FOCUS_ACCELERATOR_KEY) will be fired. * * @param aKey the key * @see #getFocusAccelerator * @beaninfo * description: accelerator character used to grab focus * bound: true */ public void setFocusAccelerator(char aKey) { aKey = Character.toUpperCase(aKey); char old = focusAccelerator; focusAccelerator = aKey; // Fix for 4341002: value of FOCUS_ACCELERATOR_KEY is wrong. // So we fire both FOCUS_ACCELERATOR_KEY, for compatibility, // and the correct event here. firePropertyChange(FOCUS_ACCELERATOR_KEY, old, focusAccelerator); firePropertyChange("focusAccelerator", old, focusAccelerator); } /** * Returns the key accelerator that will cause the receiving * text component to get the focus. Return '\0' if no focus * accelerator has been set. * * @return the key */ public char getFocusAccelerator() { return focusAccelerator; } /** * Initializes from a stream. This creates a * model of the type appropriate for the component * and initializes the model from the stream. * By default this will load the model as plain * text. Previous contents of the model are discarded. * * @param in the stream to read from * @param desc an object describing the stream; this * might be a string, a File, a URL, etc. Some kinds * of documents (such as html for example) might be * able to make use of this information; if non-<code>null</code>, * it is added as a property of the document * @exception IOException as thrown by the stream being * used to initialize * @see EditorKit#createDefaultDocument * @see #setDocument * @see PlainDocument */ public void read(Reader in, Object desc) throws IOException { EditorKit kit = getUI().getEditorKit(this); Document doc = kit.createDefaultDocument(); if (desc != null) { doc.putProperty(Document.StreamDescriptionProperty, desc); } try { kit.read(in, doc, 0); setDocument(doc); } catch (BadLocationException e) { throw new IOException(e.getMessage()); } } /** * Stores the contents of the model into the given * stream. By default this will store the model as plain * text. * * @param out the output stream * @exception IOException on any I/O error */ public void write(Writer out) throws IOException { Document doc = getDocument(); try { getUI().getEditorKit(this).write(out, doc, 0, doc.getLength()); } catch (BadLocationException e) { throw new IOException(e.getMessage()); } } public void removeNotify() { super.removeNotify(); if (getFocusedComponent() == this) { AppContext.getAppContext().remove(FOCUSED_COMPONENT); } } // --- java.awt.TextComponent methods ------------------------ /** * Sets the position of the text insertion caret for the * <code>TextComponent</code>. Note that the caret tracks change, * so this may move if the underlying text of the component is changed. * If the document is <code>null</code>, does nothing. The position * must be between 0 and the length of the component's text or else * an exception is thrown. * * @param position the position * @exception IllegalArgumentException if the value supplied * for <code>position</code> is less than zero or greater * than the component's text length * @beaninfo * description: the caret position */ public void setCaretPosition(int position) { Document doc = getDocument(); if (doc != null) { if (position > doc.getLength() || position < 0) { throw new IllegalArgumentException("bad position: " + position); } caret.setDot(position); } } /** * Returns the position of the text insertion caret for the * text component. * * @return the position of the text insertion caret for the * text component >= 0 */ @Transient public int getCaretPosition() { return caret.getDot(); } /** * Sets the text of this <code>TextComponent</code> * to the specified text. If the text is <code>null</code> * or empty, has the effect of simply deleting the old text. * When text has been inserted, the resulting caret location * is determined by the implementation of the caret class. * * <p> * Note that text is not a bound property, so no <code>PropertyChangeEvent * </code> is fired when it changes. To listen for changes to the text, * use <code>DocumentListener</code>. * * @param t the new text to be set * @see #getText * @see DefaultCaret * @beaninfo * description: the text of this component */ public void setText(String t) { try { Document doc = getDocument(); if (doc instanceof AbstractDocument) { ((AbstractDocument)doc).replace(0, doc.getLength(), t,null); } else { doc.remove(0, doc.getLength()); doc.insertString(0, t, null); } } catch (BadLocationException e) { UIManager.getLookAndFeel().provideErrorFeedback(JTextComponent.this); } } /** * Returns the text contained in this <code>TextComponent</code>. * If the underlying document is <code>null</code>, * will give a <code>NullPointerException</code>. * * Note that text is not a bound property, so no <code>PropertyChangeEvent * </code> is fired when it changes. To listen for changes to the text, * use <code>DocumentListener</code>. * * @return the text * @exception NullPointerException if the document is <code>null</code> * @see #setText */ public String getText() { Document doc = getDocument(); String txt; try { txt = doc.getText(0, doc.getLength()); } catch (BadLocationException e) { txt = null; } return txt; } /** * Returns the selected text contained in this * <code>TextComponent</code>. If the selection is * <code>null</code> or the document empty, returns <code>null</code>. * * @return the text * @exception IllegalArgumentException if the selection doesn't * have a valid mapping into the document for some reason * @see #setText */ public String getSelectedText() { String txt = null; int p0 = Math.min(caret.getDot(), caret.getMark()); int p1 = Math.max(caret.getDot(), caret.getMark()); if (p0 != p1) { try { Document doc = getDocument(); txt = doc.getText(p0, p1 - p0); } catch (BadLocationException e) { throw new IllegalArgumentException(e.getMessage()); } } return txt; } /** * Returns the boolean indicating whether this * <code>TextComponent</code> is editable or not. * * @return the boolean value * @see #setEditable */ public boolean isEditable() { return editable; } /** * Sets the specified boolean to indicate whether or not this * <code>TextComponent</code> should be editable. * A PropertyChange event ("editable") is fired when the * state is changed. * * @param b the boolean to be set * @see #isEditable * @beaninfo * description: specifies if the text can be edited * bound: true */ public void setEditable(boolean b) { if (b != editable) { boolean oldVal = editable; editable = b; enableInputMethods(editable); firePropertyChange("editable", Boolean.valueOf(oldVal), Boolean.valueOf(editable)); repaint(); } } /** * Returns the selected text's start position. Return 0 for an * empty document, or the value of dot if no selection. * * @return the start position >= 0 */ @Transient public int getSelectionStart() { int start = Math.min(caret.getDot(), caret.getMark()); return start; } /** * Sets the selection start to the specified position. The new * starting point is constrained to be before or at the current * selection end. * <p> * This is available for backward compatibility to code * that called this method on <code>java.awt.TextComponent</code>. * This is implemented to forward to the <code>Caret</code> * implementation which is where the actual selection is maintained. * * @param selectionStart the start position of the text >= 0 * @beaninfo * description: starting location of the selection. */ public void setSelectionStart(int selectionStart) { /* Route through select method to enforce consistent policy * between selectionStart and selectionEnd. */ select(selectionStart, getSelectionEnd()); } /** * Returns the selected text's end position. Return 0 if the document * is empty, or the value of dot if there is no selection. * * @return the end position >= 0 */ @Transient public int getSelectionEnd() { int end = Math.max(caret.getDot(), caret.getMark()); return end; } /** * Sets the selection end to the specified position. The new * end point is constrained to be at or after the current * selection start. * <p> * This is available for backward compatibility to code * that called this method on <code>java.awt.TextComponent</code>. * This is implemented to forward to the <code>Caret</code> * implementation which is where the actual selection is maintained. * * @param selectionEnd the end position of the text >= 0 * @beaninfo * description: ending location of the selection. */ public void setSelectionEnd(int selectionEnd) { /* Route through select method to enforce consistent policy * between selectionStart and selectionEnd. */ select(getSelectionStart(), selectionEnd); } /** * Selects the text between the specified start and end positions. * <p> * This method sets the start and end positions of the * selected text, enforcing the restriction that the start position * must be greater than or equal to zero. The end position must be * greater than or equal to the start position, and less than or * equal to the length of the text component's text. * <p> * If the caller supplies values that are inconsistent or out of * bounds, the method enforces these constraints silently, and * without failure. Specifically, if the start position or end * position is greater than the length of the text, it is reset to * equal the text length. If the start position is less than zero, * it is reset to zero, and if the end position is less than the * start position, it is reset to the start position. * <p> * This call is provided for backward compatibility. * It is routed to a call to <code>setCaretPosition</code> * followed by a call to <code>moveCaretPosition</code>. * The preferred way to manage selection is by calling * those methods directly. * * @param selectionStart the start position of the text * @param selectionEnd the end position of the text * @see #setCaretPosition * @see #moveCaretPosition */ public void select(int selectionStart, int selectionEnd) { // argument adjustment done by java.awt.TextComponent int docLength = getDocument().getLength(); if (selectionStart < 0) { selectionStart = 0; } if (selectionStart > docLength) { selectionStart = docLength; } if (selectionEnd > docLength) { selectionEnd = docLength; } if (selectionEnd < selectionStart) { selectionEnd = selectionStart; } setCaretPosition(selectionStart); moveCaretPosition(selectionEnd); } /** * Selects all the text in the <code>TextComponent</code>. * Does nothing on a <code>null</code> or empty document. */ public void selectAll() { Document doc = getDocument(); if (doc != null) { setCaretPosition(0); moveCaretPosition(doc.getLength()); } } // --- Tooltip Methods --------------------------------------------- /** * Returns the string to be used as the tooltip for <code>event</code>. * This will return one of: * <ol> * <li>If <code>setToolTipText</code> has been invoked with a * non-<code>null</code> * value, it will be returned, otherwise * <li>The value from invoking <code>getToolTipText</code> on * the UI will be returned. * </ol> * By default <code>JTextComponent</code> does not register * itself with the <code>ToolTipManager</code>. * This means that tooltips will NOT be shown from the * <code>TextUI</code> unless <code>registerComponent</code> has * been invoked on the <code>ToolTipManager</code>. * * @param event the event in question * @return the string to be used as the tooltip for <code>event</code> * @see javax.swing.JComponent#setToolTipText * @see javax.swing.plaf.TextUI#getToolTipText * @see javax.swing.ToolTipManager#registerComponent */ public String getToolTipText(MouseEvent event) { String retValue = super.getToolTipText(event); if (retValue == null) { TextUI ui = getUI(); if (ui != null) { retValue = ui.getToolTipText(this, new Point(event.getX(), event.getY())); } } return retValue; } // --- Scrollable methods --------------------------------------------- /** * Returns the preferred size of the viewport for a view component. * This is implemented to do the default behavior of returning * the preferred size of the component. * * @return the <code>preferredSize</code> of a <code>JViewport</code> * whose view is this <code>Scrollable</code> */ public Dimension getPreferredScrollableViewportSize() { return getPreferredSize(); } /** * Components that display logical rows or columns should compute * the scroll increment that will completely expose one new row * or column, depending on the value of orientation. Ideally, * components should handle a partially exposed row or column by * returning the distance required to completely expose the item. * <p> * The default implementation of this is to simply return 10% of * the visible area. Subclasses are likely to be able to provide * a much more reasonable value. *Lines 1501–2000 of 5073. Previous lines Load more
*/ private void invokeAction(String name, Action altAction) { ActionMap map = getActionMap(); Action action = null; if (map != null) { action = map.get(name); } if (action == null) { installDefaultTransferHandlerIfNecessary(); action = altAction; } action.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, (String)action. getValue(Action.NAME), EventQueue.getMostRecentEventTime(), getCurrentEventModifiers())); } /** * If the current <code>TransferHandler</code> is null, this will * install a new one. */ private void installDefaultTransferHandlerIfNecessary() { if (getTransferHandler() == null) { if (defaultTransferHandler == null) { defaultTransferHandler = new DefaultTransferHandler(); } setTransferHandler(defaultTransferHandler); } } /** * Moves the caret to a new position, leaving behind a mark * defined by the last time <code>setCaretPosition</code> was * called. This forms a selection. * If the document is <code>null</code>, does nothing. The position * must be between 0 and the length of the component's text or else * an exception is thrown. * * @param pos the position * @exception IllegalArgumentException if the value supplied * for <code>position</code> is less than zero or greater * than the component's text length * @see #setCaretPosition */ public void moveCaretPosition(int pos) { Document doc = getDocument(); if (doc != null) { if (pos > doc.getLength() || pos < 0) { throw new IllegalArgumentException("bad position: " + pos); } caret.moveDot(pos); } } /** * The bound property name for the focus accelerator. */ public static final String FOCUS_ACCELERATOR_KEY = "focusAcceleratorKey"; /** * Sets the key accelerator that will cause the receiving text * component to get the focus. The accelerator will be the * key combination of the <em>alt</em> key and the character * given (converted to upper case). By default, there is no focus * accelerator key. Any previous key accelerator setting will be * superseded. A '\0' key setting will be registered, and has the * effect of turning off the focus accelerator. When the new key * is set, a PropertyChange event (FOCUS_ACCELERATOR_KEY) will be fired. * * @param aKey the key * @see #getFocusAccelerator * @beaninfo * description: accelerator character used to grab focus * bound: true */ public void setFocusAccelerator(char aKey) { aKey = Character.toUpperCase(aKey); char old = focusAccelerator; focusAccelerator = aKey; // Fix for 4341002: value of FOCUS_ACCELERATOR_KEY is wrong. // So we fire both FOCUS_ACCELERATOR_KEY, for compatibility, // and the correct event here. firePropertyChange(FOCUS_ACCELERATOR_KEY, old, focusAccelerator); firePropertyChange("focusAccelerator", old, focusAccelerator); } /** * Returns the key accelerator that will cause the receiving * text component to get the focus. Return '\0' if no focus * accelerator has been set. * * @return the key */ public char getFocusAccelerator() { return focusAccelerator; } /** * Initializes from a stream. This creates a * model of the type appropriate for the component * and initializes the model from the stream. * By default this will load the model as plain * text. Previous contents of the model are discarded. * * @param in the stream to read from * @param desc an object describing the stream; this * might be a string, a File, a URL, etc. Some kinds * of documents (such as html for example) might be * able to make use of this information; if non-<code>null</code>, * it is added as a property of the document * @exception IOException as thrown by the stream being * used to initialize * @see EditorKit#createDefaultDocument * @see #setDocument * @see PlainDocument */ public void read(Reader in, Object desc) throws IOException { EditorKit kit = getUI().getEditorKit(this); Document doc = kit.createDefaultDocument(); if (desc != null) { doc.putProperty(Document.StreamDescriptionProperty, desc); } try { kit.read(in, doc, 0); setDocument(doc); } catch (BadLocationException e) { throw new IOException(e.getMessage()); } } /** * Stores the contents of the model into the given * stream. By default this will store the model as plain * text. * * @param out the output stream * @exception IOException on any I/O error */ public void write(Writer out) throws IOException { Document doc = getDocument(); try { getUI().getEditorKit(this).write(out, doc, 0, doc.getLength()); } catch (BadLocationException e) { throw new IOException(e.getMessage()); } } public void removeNotify() { super.removeNotify(); if (getFocusedComponent() == this) { AppContext.getAppContext().remove(FOCUSED_COMPONENT); } } // --- java.awt.TextComponent methods ------------------------ /** * Sets the position of the text insertion caret for the * <code>TextComponent</code>. Note that the caret tracks change, * so this may move if the underlying text of the component is changed. * If the document is <code>null</code>, does nothing. The position * must be between 0 and the length of the component's text or else * an exception is thrown. * * @param position the position * @exception IllegalArgumentException if the value supplied * for <code>position</code> is less than zero or greater * than the component's text length * @beaninfo * description: the caret position */ public void setCaretPosition(int position) { Document doc = getDocument(); if (doc != null) { if (position > doc.getLength() || position < 0) { throw new IllegalArgumentException("bad position: " + position); } caret.setDot(position); } } /** * Returns the position of the text insertion caret for the * text component. * * @return the position of the text insertion caret for the * text component >= 0 */ @Transient public int getCaretPosition() { return caret.getDot(); } /** * Sets the text of this <code>TextComponent</code> * to the specified text. If the text is <code>null</code> * or empty, has the effect of simply deleting the old text. * When text has been inserted, the resulting caret location * is determined by the implementation of the caret class. * * <p> * Note that text is not a bound property, so no <code>PropertyChangeEvent * </code> is fired when it changes. To listen for changes to the text, * use <code>DocumentListener</code>. * * @param t the new text to be set * @see #getText * @see DefaultCaret * @beaninfo * description: the text of this component */ public void setText(String t) { try { Document doc = getDocument(); if (doc instanceof AbstractDocument) { ((AbstractDocument)doc).replace(0, doc.getLength(), t,null); } else { doc.remove(0, doc.getLength()); doc.insertString(0, t, null); } } catch (BadLocationException e) { UIManager.getLookAndFeel().provideErrorFeedback(JTextComponent.this); } } /** * Returns the text contained in this <code>TextComponent</code>. * If the underlying document is <code>null</code>, * will give a <code>NullPointerException</code>. * * Note that text is not a bound property, so no <code>PropertyChangeEvent * </code> is fired when it changes. To listen for changes to the text, * use <code>DocumentListener</code>. * * @return the text * @exception NullPointerException if the document is <code>null</code> * @see #setText */ public String getText() { Document doc = getDocument(); String txt; try { txt = doc.getText(0, doc.getLength()); } catch (BadLocationException e) { txt = null; } return txt; } /** * Returns the selected text contained in this * <code>TextComponent</code>. If the selection is * <code>null</code> or the document empty, returns <code>null</code>. * * @return the text * @exception IllegalArgumentException if the selection doesn't * have a valid mapping into the document for some reason * @see #setText */ public String getSelectedText() { String txt = null; int p0 = Math.min(caret.getDot(), caret.getMark()); int p1 = Math.max(caret.getDot(), caret.getMark()); if (p0 != p1) { try { Document doc = getDocument(); txt = doc.getText(p0, p1 - p0); } catch (BadLocationException e) { throw new IllegalArgumentException(e.getMessage()); } } return txt; } /** * Returns the boolean indicating whether this * <code>TextComponent</code> is editable or not. * * @return the boolean value * @see #setEditable */ public boolean isEditable() { return editable; } /** * Sets the specified boolean to indicate whether or not this * <code>TextComponent</code> should be editable. * A PropertyChange event ("editable") is fired when the * state is changed. * * @param b the boolean to be set * @see #isEditable * @beaninfo * description: specifies if the text can be edited * bound: true */ public void setEditable(boolean b) { if (b != editable) { boolean oldVal = editable; editable = b; enableInputMethods(editable); firePropertyChange("editable", Boolean.valueOf(oldVal), Boolean.valueOf(editable)); repaint(); } } /** * Returns the selected text's start position. Return 0 for an * empty document, or the value of dot if no selection. * * @return the start position >= 0 */ @Transient public int getSelectionStart() { int start = Math.min(caret.getDot(), caret.getMark()); return start; } /** * Sets the selection start to the specified position. The new * starting point is constrained to be before or at the current * selection end. * <p> * This is available for backward compatibility to code * that called this method on <code>java.awt.TextComponent</code>. * This is implemented to forward to the <code>Caret</code> * implementation which is where the actual selection is maintained. * * @param selectionStart the start position of the text >= 0 * @beaninfo * description: starting location of the selection. */ public void setSelectionStart(int selectionStart) { /* Route through select method to enforce consistent policy * between selectionStart and selectionEnd. */ select(selectionStart, getSelectionEnd()); } /** * Returns the selected text's end position. Return 0 if the document * is empty, or the value of dot if there is no selection. * * @return the end position >= 0 */ @Transient public int getSelectionEnd() { int end = Math.max(caret.getDot(), caret.getMark()); return end; } /** * Sets the selection end to the specified position. The new * end point is constrained to be at or after the current * selection start. * <p> * This is available for backward compatibility to code * that called this method on <code>java.awt.TextComponent</code>. * This is implemented to forward to the <code>Caret</code> * implementation which is where the actual selection is maintained. * * @param selectionEnd the end position of the text >= 0 * @beaninfo * description: ending location of the selection. */ public void setSelectionEnd(int selectionEnd) { /* Route through select method to enforce consistent policy * between selectionStart and selectionEnd. */ select(getSelectionStart(), selectionEnd); } /** * Selects the text between the specified start and end positions. * <p> * This method sets the start and end positions of the * selected text, enforcing the restriction that the start position * must be greater than or equal to zero. The end position must be * greater than or equal to the start position, and less than or * equal to the length of the text component's text. * <p> * If the caller supplies values that are inconsistent or out of * bounds, the method enforces these constraints silently, and * without failure. Specifically, if the start position or end * position is greater than the length of the text, it is reset to * equal the text length. If the start position is less than zero, * it is reset to zero, and if the end position is less than the * start position, it is reset to the start position. * <p> * This call is provided for backward compatibility. * It is routed to a call to <code>setCaretPosition</code> * followed by a call to <code>moveCaretPosition</code>. * The preferred way to manage selection is by calling * those methods directly. * * @param selectionStart the start position of the text * @param selectionEnd the end position of the text * @see #setCaretPosition * @see #moveCaretPosition */ public void select(int selectionStart, int selectionEnd) { // argument adjustment done by java.awt.TextComponent int docLength = getDocument().getLength(); if (selectionStart < 0) { selectionStart = 0; } if (selectionStart > docLength) { selectionStart = docLength; } if (selectionEnd > docLength) { selectionEnd = docLength; } if (selectionEnd < selectionStart) { selectionEnd = selectionStart; } setCaretPosition(selectionStart); moveCaretPosition(selectionEnd); } /** * Selects all the text in the <code>TextComponent</code>. * Does nothing on a <code>null</code> or empty document. */ public void selectAll() { Document doc = getDocument(); if (doc != null) { setCaretPosition(0); moveCaretPosition(doc.getLength()); } } // --- Tooltip Methods --------------------------------------------- /** * Returns the string to be used as the tooltip for <code>event</code>. * This will return one of: * <ol> * <li>If <code>setToolTipText</code> has been invoked with a * non-<code>null</code> * value, it will be returned, otherwise * <li>The value from invoking <code>getToolTipText</code> on * the UI will be returned. * </ol> * By default <code>JTextComponent</code> does not register * itself with the <code>ToolTipManager</code>. * This means that tooltips will NOT be shown from the * <code>TextUI</code> unless <code>registerComponent</code> has * been invoked on the <code>ToolTipManager</code>. * * @param event the event in question * @return the string to be used as the tooltip for <code>event</code> * @see javax.swing.JComponent#setToolTipText * @see javax.swing.plaf.TextUI#getToolTipText * @see javax.swing.ToolTipManager#registerComponent */ public String getToolTipText(MouseEvent event) { String retValue = super.getToolTipText(event); if (retValue == null) { TextUI ui = getUI(); if (ui != null) { retValue = ui.getToolTipText(this, new Point(event.getX(), event.getY())); } } return retValue; } // --- Scrollable methods --------------------------------------------- /** * Returns the preferred size of the viewport for a view component. * This is implemented to do the default behavior of returning * the preferred size of the component. * * @return the <code>preferredSize</code> of a <code>JViewport</code> * whose view is this <code>Scrollable</code> */ public Dimension getPreferredScrollableViewportSize() { return getPreferredSize(); } /** * Components that display logical rows or columns should compute * the scroll increment that will completely expose one new row * or column, depending on the value of orientation. Ideally, * components should handle a partially exposed row or column by * returning the distance required to completely expose the item. * <p> * The default implementation of this is to simply return 10% of * the visible area. Subclasses are likely to be able to provide * a much more reasonable value. *