IDEA-67172 "Empty text" feature in EditorTextField

Added ability to specify editor's 'placeholder text'
This commit is contained in:
Denis Zhdanov
2011-03-29 19:20:41 +04:00
parent 8175f2bc7b
commit 810074407e
4 changed files with 66 additions and 0 deletions
@@ -625,4 +625,9 @@ public class EditorWindow extends UserDataHolderBase implements EditorEx {
public void setSoftWrapAppliancePlace(@NotNull SoftWrapAppliancePlaces place) {
myDelegate.setSoftWrapAppliancePlace(place);
}
@Override
public void setPlaceholder(@Nullable CharSequence text) {
myDelegate.setPlaceholder(text);
}
}
@@ -164,4 +164,15 @@ public interface EditorEx extends Editor {
* @param place soft wraps appliance appliance use-case
*/
void setSoftWrapAppliancePlace(@NotNull SoftWrapAppliancePlaces place);
/**
* Allows to define <code>'placeholder text'</code> for the current editor, i.e. virtual text that will be represented until
* any user data is entered and current editor is not focused.
* <p/>
* Feel free to see the detailed feature
* definition <a href="http://dev.w3.org/html5/spec/Overview.html#the-placeholder-attribute">here</a>.
*
* @param text virtual text to show until user data is entered or the editor is focused
*/
void setPlaceholder(@Nullable CharSequence text);
}
@@ -259,6 +259,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
private char[] myPrefixText;
private TextAttributes myPrefixAttributes;
private final IndentsModel myIndentsModel;
@Nullable
private CharSequence myPlaceholderText;
private int myLastPaintedPlaceholderWidth;
static {
ourCaretBlinkingCommand = new RepaintCursorCommand();
@@ -1549,6 +1553,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
paintLineMarkersSeparators(g, clip, docMarkup);
paintLineMarkersSeparators(g, clip, myMarkupModel);
paintText(g, clip);
paintPlaceholderText(g, clip);
paintSegmentHighlightersBorderAndAfterEndOfLine(g, clip);
BorderEffect borderEffect = new BorderEffect(this, g);
borderEffect.paintHighlighters(getHighlighter());
@@ -1625,6 +1630,11 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
return myTextDrawingCallback;
}
@Override
public void setPlaceholder(@Nullable CharSequence text) {
myPlaceholderText = text;
}
private Color getBackgroundColor(final TextAttributes attributes) {
final Color attrColor = attributes.getBackgroundColor();
return attrColor == myScheme.getDefaultBackground() ? getBackgroundColor() : attrColor;
@@ -2331,6 +2341,29 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
flushCachedChars(g);
}
private void paintPlaceholderText(Graphics g, Rectangle clip) {
CharSequence hintText = myPlaceholderText;
if (myDocument.getTextLength() > 0 || hintText == null || hintText.length() == 0) {
return;
}
if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() == myEditorComponent) {
// There is a possible case that placeholder text was painted and the editor gets focus now. We want to over-paint previuosly
// used placeholder text then.
myLastBackgroundColor = getBackgroundColor();
myLastBackgroundPosition = new Point(0, 0);
myLastBackgroundWidth = myLastPaintedPlaceholderWidth;
flushBackground(g, clip);
}
else {
myLastPaintedPlaceholderWidth = drawString(
g, CharArrayUtil.fromSequence(hintText), 0, hintText.length(), new Point(0, 0), clip, null, null, Font.PLAIN,
myFoldingModel.getPlaceholderAttributes().getForegroundColor()
);
flushCachedChars(g);
}
}
private boolean paintSelection() {
return !isOneLineMode() || IJSwingUtilities.hasFocus(getContentComponent());
}
@@ -76,6 +76,7 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener,
private boolean myCenterByHeight = true;
private boolean myEnsureWillComputePreferredSize;
private Dimension myPassivePreferredSize;
private CharSequence myHintText;
public EditorTextField() {
this("");
@@ -250,6 +251,20 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener,
});
}
/**
* Allows to define {@link EditorEx#setPlaceholder(CharSequence) editor's placeholder}. The trick here is that the editor
* is instantiated lazily by the editor text field and provided placeholder text is applied to the editor during its
* actual construction then.
*
* @param text {@link EditorEx#setPlaceholder(CharSequence) editor's placeholder} text to use
*/
public void setPlaceholder(@Nullable CharSequence text) {
myHintText = text;
if (myEditor != null) {
myEditor.setPlaceholder(text);
}
}
public void selectAll() {
if (myEditor != null) {
myEditor.getSelectionModel().setSelection(0, myDocument.getTextLength());
@@ -485,6 +500,8 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener,
editor.putUserData(SUPPLEMENTARY_KEY, myIsSupplementary);
editor.getContentComponent().setFocusCycleRoot(false);
editor.setPlaceholder(myHintText);
initOneLineMode(editor);