mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2026-02-13 23:37:13 -06:00
TextField: support leading and trailing components
This commit is contained in:
@@ -30,7 +30,10 @@ FlatLaf Change Log
|
|||||||
(issue #416)
|
(issue #416)
|
||||||
- TextField, FormattedTextField and PasswordField: Support leading and trailing
|
- TextField, FormattedTextField and PasswordField: Support leading and trailing
|
||||||
icons (set client property `JTextField.leadingIcon` or
|
icons (set client property `JTextField.leadingIcon` or
|
||||||
`JTextField.trailingIcon` to an `Icon`). (PR #378; issue #368)
|
`JTextField.trailingIcon` to a `javax.swing.Icon`). (PR #378; issue #368)
|
||||||
|
- TextField, FormattedTextField and PasswordField: Support leading and trailing
|
||||||
|
components (set client property `JTextField.leadingComponent` or
|
||||||
|
`JTextField.trailingComponent` to a `java.awt.Component`). (PR #386)
|
||||||
- TextComponents: Double/triple-click-and-drag now extends selection by whole
|
- TextComponents: Double/triple-click-and-drag now extends selection by whole
|
||||||
words/lines.
|
words/lines.
|
||||||
- Theming improvements: Reworks core themes to make it easier to create new
|
- Theming improvements: Reworks core themes to make it easier to create new
|
||||||
|
|||||||
@@ -763,9 +763,9 @@ public interface FlatClientProperties
|
|||||||
/**
|
/**
|
||||||
* Specifies a component that will be placed at the leading edge of the tabs area.
|
* Specifies a component that will be placed at the leading edge of the tabs area.
|
||||||
* <p>
|
* <p>
|
||||||
* For top and bottom tab placement, the layed out component size will be
|
* For top and bottom tab placement, the laid out component size will be
|
||||||
* the preferred component width and the tab area height.<br>
|
* the preferred component width and the tab area height.<br>
|
||||||
* For left and right tab placement, the layed out component size will be
|
* For left and right tab placement, the laid out component size will be
|
||||||
* the tab area width and the preferred component height.
|
* the tab area width and the preferred component height.
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
||||||
@@ -776,9 +776,9 @@ public interface FlatClientProperties
|
|||||||
/**
|
/**
|
||||||
* Specifies a component that will be placed at the trailing edge of the tabs area.
|
* Specifies a component that will be placed at the trailing edge of the tabs area.
|
||||||
* <p>
|
* <p>
|
||||||
* For top and bottom tab placement, the layed out component size will be
|
* For top and bottom tab placement, the laid out component size will be
|
||||||
* the available horizontal space (minimum is preferred component width) and the tab area height.<br>
|
* the available horizontal space (minimum is preferred component width) and the tab area height.<br>
|
||||||
* For left and right tab placement, the layed out component size will be
|
* For left and right tab placement, the laid out component size will be
|
||||||
* the tab area width and the available vertical space (minimum is preferred component height).
|
* the tab area width and the available vertical space (minimum is preferred component height).
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
||||||
@@ -863,6 +863,46 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String TEXT_FIELD_TRAILING_ICON = "JTextField.trailingIcon";
|
String TEXT_FIELD_TRAILING_ICON = "JTextField.trailingIcon";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies a component that will be placed at the leading edge of the text field.
|
||||||
|
* <p>
|
||||||
|
* The component will be positioned inside and aligned to the visible text field border.
|
||||||
|
* There is no gap between the visible border and the component.
|
||||||
|
* The laid out component size will be the preferred component width
|
||||||
|
* and the inner text field height.
|
||||||
|
* <p>
|
||||||
|
* The component should be not opaque because the text field border is painted
|
||||||
|
* slightly inside the usually visible border in some cases.
|
||||||
|
* E.g. when focused (in some themes) or when an outline color is specified
|
||||||
|
* (see {@link #OUTLINE}.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||||
|
* <strong>Value type</strong> {@link java.awt.Component}
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String TEXT_FIELD_LEADING_COMPONENT = "JTextField.leadingComponent";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies a component that will be placed at the trailing edge of the text field.
|
||||||
|
* <p>
|
||||||
|
* The component will be positioned inside and aligned to the visible text field border.
|
||||||
|
* There is no gap between the visible border and the component.
|
||||||
|
* The laid out component size will be the preferred component width
|
||||||
|
* and the inner text field height.
|
||||||
|
* <p>
|
||||||
|
* The component should be not opaque because the text field border is painted
|
||||||
|
* slightly inside the usually visible border in some cases.
|
||||||
|
* E.g. when focused (in some themes) or when an outline color is specified
|
||||||
|
* (see {@link #OUTLINE}.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||||
|
* <strong>Value type</strong> {@link java.awt.Component}
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String TEXT_FIELD_TRAILING_COMPONENT = "JTextField.trailingComponent";
|
||||||
|
|
||||||
//---- JToggleButton ------------------------------------------------------
|
//---- JToggleButton ------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -19,12 +19,15 @@ package com.formdev.flatlaf.ui;
|
|||||||
import static com.formdev.flatlaf.FlatClientProperties.*;
|
import static com.formdev.flatlaf.FlatClientProperties.*;
|
||||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
import java.awt.Container;
|
import java.awt.Container;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.FontMetrics;
|
import java.awt.FontMetrics;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
|
import java.awt.LayoutManager;
|
||||||
|
import java.awt.LayoutManager2;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
import java.awt.event.FocusListener;
|
import java.awt.event.FocusListener;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
@@ -94,6 +97,8 @@ public class FlatTextFieldUI
|
|||||||
|
|
||||||
/** @since 2 */ @Styleable protected Icon leadingIcon;
|
/** @since 2 */ @Styleable protected Icon leadingIcon;
|
||||||
/** @since 2 */ @Styleable protected Icon trailingIcon;
|
/** @since 2 */ @Styleable protected Icon trailingIcon;
|
||||||
|
/** @since 2 */ protected Component leadingComponent;
|
||||||
|
/** @since 2 */ protected Component trailingComponent;
|
||||||
|
|
||||||
private Color oldDisabledBackground;
|
private Color oldDisabledBackground;
|
||||||
private Color oldInactiveBackground;
|
private Color oldInactiveBackground;
|
||||||
@@ -115,11 +120,17 @@ public class FlatTextFieldUI
|
|||||||
leadingIcon = clientProperty( c, TEXT_FIELD_LEADING_ICON, null, Icon.class );
|
leadingIcon = clientProperty( c, TEXT_FIELD_LEADING_ICON, null, Icon.class );
|
||||||
trailingIcon = clientProperty( c, TEXT_FIELD_TRAILING_ICON, null, Icon.class );
|
trailingIcon = clientProperty( c, TEXT_FIELD_TRAILING_ICON, null, Icon.class );
|
||||||
|
|
||||||
|
installLeadingComponent();
|
||||||
|
installTrailingComponent();
|
||||||
|
|
||||||
installStyle();
|
installStyle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void uninstallUI( JComponent c ) {
|
public void uninstallUI( JComponent c ) {
|
||||||
|
uninstallLeadingComponent();
|
||||||
|
uninstallTrailingComponent();
|
||||||
|
|
||||||
super.uninstallUI( c );
|
super.uninstallUI( c );
|
||||||
|
|
||||||
leadingIcon = null;
|
leadingIcon = null;
|
||||||
@@ -225,6 +236,20 @@ public class FlatTextFieldUI
|
|||||||
trailingIcon = (e.getNewValue() instanceof Icon) ? (Icon) e.getNewValue() : null;
|
trailingIcon = (e.getNewValue() instanceof Icon) ? (Icon) e.getNewValue() : null;
|
||||||
c.repaint();
|
c.repaint();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TEXT_FIELD_LEADING_COMPONENT:
|
||||||
|
uninstallLeadingComponent();
|
||||||
|
installLeadingComponent();
|
||||||
|
c.revalidate();
|
||||||
|
c.repaint();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TEXT_FIELD_TRAILING_COMPONENT:
|
||||||
|
uninstallTrailingComponent();
|
||||||
|
installTrailingComponent();
|
||||||
|
c.revalidate();
|
||||||
|
c.repaint();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,6 +469,12 @@ debug*/
|
|||||||
// add width of leading and trailing icons
|
// add width of leading and trailing icons
|
||||||
size.width += getLeadingIconWidth() + getTrailingIconWidth();
|
size.width += getLeadingIconWidth() + getTrailingIconWidth();
|
||||||
|
|
||||||
|
// add width of leading and trailing components
|
||||||
|
if( leadingComponent != null && leadingComponent.isVisible() )
|
||||||
|
size.width += leadingComponent.getPreferredSize().width;
|
||||||
|
if( trailingComponent != null && trailingComponent.isVisible() )
|
||||||
|
size.width += trailingComponent.getPreferredSize().width;
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -510,7 +541,8 @@ debug*/
|
|||||||
/**
|
/**
|
||||||
* Returns the rectangle used to paint leading and trailing icons.
|
* Returns the rectangle used to paint leading and trailing icons.
|
||||||
* It invokes {@code super.getVisibleEditorRect()} and reduces left and/or
|
* It invokes {@code super.getVisibleEditorRect()} and reduces left and/or
|
||||||
* right margin if the text field has leading or trailing icons.
|
* right margin if the text field has leading or trailing icons or components.
|
||||||
|
* Also the preferred widths of leading and trailing components are removed.
|
||||||
*
|
*
|
||||||
* @since 2
|
* @since 2
|
||||||
*/
|
*/
|
||||||
@@ -519,10 +551,24 @@ debug*/
|
|||||||
if( r == null )
|
if( r == null )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// if a leading/trailing icon is shown, then the left/right margin is reduced
|
|
||||||
// to the top margin, which places the icon nicely centered on left/right side
|
|
||||||
boolean ltr = isLeftToRight();
|
boolean ltr = isLeftToRight();
|
||||||
if( ltr ? hasLeadingIcon() : hasTrailingIcon() ) {
|
|
||||||
|
// remove width of leading/trailing components
|
||||||
|
Component leftComponent = ltr ? leadingComponent : trailingComponent;
|
||||||
|
Component rightComponent = ltr ? trailingComponent : leadingComponent;
|
||||||
|
if( leftComponent != null ) {
|
||||||
|
int w = leftComponent.getPreferredSize().width;
|
||||||
|
r.x += w;
|
||||||
|
r.width -= w;
|
||||||
|
}
|
||||||
|
if( rightComponent != null )
|
||||||
|
r.width -= rightComponent.getPreferredSize().width;
|
||||||
|
|
||||||
|
// if a leading/trailing icons (or components) are shown, then the left/right margins are reduced
|
||||||
|
// to the top margin, which places the icon nicely centered on left/right side
|
||||||
|
if( (ltr ? hasLeadingIcon() : hasTrailingIcon()) ||
|
||||||
|
(leftComponent != null && leftComponent.isVisible()) )
|
||||||
|
{
|
||||||
// reduce left margin
|
// reduce left margin
|
||||||
Insets margin = getComponent().getMargin();
|
Insets margin = getComponent().getMargin();
|
||||||
int newLeftMargin = Math.min( margin.left, margin.top );
|
int newLeftMargin = Math.min( margin.left, margin.top );
|
||||||
@@ -532,7 +578,9 @@ debug*/
|
|||||||
r.width += diff;
|
r.width += diff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( ltr ? hasTrailingIcon() : hasLeadingIcon() ) {
|
if( (ltr ? hasTrailingIcon() : hasLeadingIcon()) ||
|
||||||
|
(rightComponent != null && rightComponent.isVisible()) )
|
||||||
|
{
|
||||||
// reduce right margin
|
// reduce right margin
|
||||||
Insets margin = getComponent().getMargin();
|
Insets margin = getComponent().getMargin();
|
||||||
int newRightMargin = Math.min( margin.right, margin.top );
|
int newRightMargin = Math.min( margin.right, margin.top );
|
||||||
@@ -540,6 +588,10 @@ debug*/
|
|||||||
r.width += scale( margin.right - newRightMargin );
|
r.width += scale( margin.right - newRightMargin );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// make sure that width and height are not negative
|
||||||
|
r.width = Math.max( r.width, 0 );
|
||||||
|
r.height = Math.max( r.height, 0 );
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -578,4 +630,135 @@ debug*/
|
|||||||
if( caret instanceof FlatCaret )
|
if( caret instanceof FlatCaret )
|
||||||
((FlatCaret)caret).scrollCaretToVisible();
|
((FlatCaret)caret).scrollCaretToVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected void installLeadingComponent() {
|
||||||
|
JTextComponent c = getComponent();
|
||||||
|
leadingComponent = clientProperty( c, TEXT_FIELD_LEADING_COMPONENT, null, Component.class );
|
||||||
|
if( leadingComponent != null ) {
|
||||||
|
installLayout();
|
||||||
|
c.add( leadingComponent );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected void installTrailingComponent() {
|
||||||
|
JTextComponent c = getComponent();
|
||||||
|
trailingComponent = clientProperty( c, TEXT_FIELD_TRAILING_COMPONENT, null, Component.class );
|
||||||
|
if( trailingComponent != null ) {
|
||||||
|
installLayout();
|
||||||
|
c.add( trailingComponent );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected void uninstallLeadingComponent() {
|
||||||
|
if( leadingComponent != null ) {
|
||||||
|
getComponent().remove( leadingComponent );
|
||||||
|
leadingComponent = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected void uninstallTrailingComponent() {
|
||||||
|
if( trailingComponent != null ) {
|
||||||
|
getComponent().remove( trailingComponent );
|
||||||
|
trailingComponent = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void installLayout() {
|
||||||
|
JTextComponent c = getComponent();
|
||||||
|
LayoutManager oldLayout = c.getLayout();
|
||||||
|
if( !(oldLayout instanceof FlatTextFieldLayout) )
|
||||||
|
c.setLayout( new FlatTextFieldLayout( oldLayout ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- class FlatTextFieldLayout ------------------------------------------
|
||||||
|
|
||||||
|
private class FlatTextFieldLayout
|
||||||
|
implements LayoutManager2, UIResource
|
||||||
|
{
|
||||||
|
private final LayoutManager delegate;
|
||||||
|
|
||||||
|
FlatTextFieldLayout( LayoutManager delegate ) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addLayoutComponent( String name, Component comp ) {
|
||||||
|
if( delegate != null )
|
||||||
|
delegate.addLayoutComponent( name, comp );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeLayoutComponent( Component comp ) {
|
||||||
|
if( delegate != null )
|
||||||
|
delegate.removeLayoutComponent( comp );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dimension preferredLayoutSize( Container parent ) {
|
||||||
|
return (delegate != null) ? delegate.preferredLayoutSize( parent ) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dimension minimumLayoutSize( Container parent ) {
|
||||||
|
return (delegate != null) ? delegate.minimumLayoutSize( parent ) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void layoutContainer( Container parent ) {
|
||||||
|
if( delegate != null )
|
||||||
|
delegate.layoutContainer( parent );
|
||||||
|
|
||||||
|
if( leadingComponent == null && trailingComponent == null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
int ow = FlatUIUtils.getBorderFocusAndLineWidth( getComponent() );
|
||||||
|
int h = parent.getHeight() - ow - ow;
|
||||||
|
boolean ltr = isLeftToRight();
|
||||||
|
Component leftComponent = ltr ? leadingComponent : trailingComponent;
|
||||||
|
Component rightComponent = ltr ? trailingComponent : leadingComponent;
|
||||||
|
|
||||||
|
// layout left component
|
||||||
|
if( leftComponent != null && leftComponent.isVisible() ) {
|
||||||
|
int w = leftComponent.getPreferredSize().width;
|
||||||
|
leftComponent.setBounds( ow, ow, w, h );
|
||||||
|
}
|
||||||
|
|
||||||
|
// layout right component
|
||||||
|
if( rightComponent != null && rightComponent.isVisible() ) {
|
||||||
|
int w = rightComponent.getPreferredSize().width;
|
||||||
|
rightComponent.setBounds( parent.getWidth() - ow - w, ow, w, h );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addLayoutComponent( Component comp, Object constraints ) {
|
||||||
|
if( delegate instanceof LayoutManager2 )
|
||||||
|
((LayoutManager2)delegate).addLayoutComponent( comp, constraints );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dimension maximumLayoutSize( Container target ) {
|
||||||
|
return (delegate instanceof LayoutManager2) ? ((LayoutManager2)delegate).maximumLayoutSize( target ) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getLayoutAlignmentX( Container target ) {
|
||||||
|
return (delegate instanceof LayoutManager2) ? ((LayoutManager2)delegate).getLayoutAlignmentX( target ) : 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getLayoutAlignmentY( Container target ) {
|
||||||
|
return (delegate instanceof LayoutManager2) ? ((LayoutManager2)delegate).getLayoutAlignmentY( target ) : 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidateLayout( Container target ) {
|
||||||
|
if( delegate instanceof LayoutManager2 )
|
||||||
|
((LayoutManager2)delegate).invalidateLayout( target );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -278,6 +278,32 @@ public class FlatUIUtils
|
|||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the scaled line thickness used to compute the border insets.
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
public static float getBorderLineWidth( JComponent c ) {
|
||||||
|
FlatBorder border = getOutsideFlatBorder( c );
|
||||||
|
return (border != null)
|
||||||
|
? UIScale.scale( (float) border.getLineWidth( c ) )
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the scaled thickness of the border.
|
||||||
|
* This includes the outer focus border and the actual component border.
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
public static int getBorderFocusAndLineWidth( JComponent c ) {
|
||||||
|
FlatBorder border = getOutsideFlatBorder( c );
|
||||||
|
return (border != null)
|
||||||
|
? Math.round( UIScale.scale( (float) border.getFocusWidth( c ) )
|
||||||
|
+ UIScale.scale( (float) border.getLineWidth( c ) ) )
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the scaled arc diameter of the border for the given component.
|
* Returns the scaled arc diameter of the border for the given component.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.formdev.flatlaf.extras.components;
|
|||||||
|
|
||||||
import static com.formdev.flatlaf.FlatClientProperties.*;
|
import static com.formdev.flatlaf.FlatClientProperties.*;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.JFormattedTextField;
|
import javax.swing.JFormattedTextField;
|
||||||
@@ -85,6 +86,64 @@ public class FlatFormattedTextField
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a component that will be placed at the leading edge of the text field.
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
public Component getLeadingComponent() {
|
||||||
|
return (Component) getClientProperty( TEXT_FIELD_LEADING_COMPONENT );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies a component that will be placed at the leading edge of the text field.
|
||||||
|
* <p>
|
||||||
|
* The component will be positioned inside and aligned to the visible text field border.
|
||||||
|
* There is no gap between the visible border and the component.
|
||||||
|
* The laid out component size will be the preferred component width
|
||||||
|
* and the inner text field height.
|
||||||
|
* <p>
|
||||||
|
* The component should be not opaque because the text field border is painted
|
||||||
|
* slightly inside the usually visible border in some cases.
|
||||||
|
* E.g. when focused (in some themes) or when an outline color is specified
|
||||||
|
* (see {@link #setOutline(Object)}.
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
public void setLeadingComponent( Component leadingComponent ) {
|
||||||
|
putClientProperty( TEXT_FIELD_LEADING_COMPONENT, leadingComponent );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a component that will be placed at the trailing edge of the text field.
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
public Component getTrailingComponent() {
|
||||||
|
return (Component) getClientProperty( TEXT_FIELD_TRAILING_COMPONENT );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies a component that will be placed at the trailing edge of the text field.
|
||||||
|
* <p>
|
||||||
|
* The component will be positioned inside and aligned to the visible text field border.
|
||||||
|
* There is no gap between the visible border and the component.
|
||||||
|
* The laid out component size will be the preferred component width
|
||||||
|
* and the inner text field height.
|
||||||
|
* <p>
|
||||||
|
* The component should be not opaque because the text field border is painted
|
||||||
|
* slightly inside the usually visible border in some cases.
|
||||||
|
* E.g. when focused (in some themes) or when an outline color is specified
|
||||||
|
* (see {@link #setOutline(Object)}.
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
public void setTrailingComponent( Component trailingComponent ) {
|
||||||
|
putClientProperty( TEXT_FIELD_TRAILING_COMPONENT, trailingComponent );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether all text is selected when the text component gains focus.
|
* Returns whether all text is selected when the text component gains focus.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.formdev.flatlaf.extras.components;
|
|||||||
|
|
||||||
import static com.formdev.flatlaf.FlatClientProperties.*;
|
import static com.formdev.flatlaf.FlatClientProperties.*;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.JPasswordField;
|
import javax.swing.JPasswordField;
|
||||||
@@ -85,6 +86,64 @@ public class FlatPasswordField
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a component that will be placed at the leading edge of the text field.
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
public Component getLeadingComponent() {
|
||||||
|
return (Component) getClientProperty( TEXT_FIELD_LEADING_COMPONENT );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies a component that will be placed at the leading edge of the text field.
|
||||||
|
* <p>
|
||||||
|
* The component will be positioned inside and aligned to the visible text field border.
|
||||||
|
* There is no gap between the visible border and the component.
|
||||||
|
* The laid out component size will be the preferred component width
|
||||||
|
* and the inner text field height.
|
||||||
|
* <p>
|
||||||
|
* The component should be not opaque because the text field border is painted
|
||||||
|
* slightly inside the usually visible border in some cases.
|
||||||
|
* E.g. when focused (in some themes) or when an outline color is specified
|
||||||
|
* (see {@link #setOutline(Object)}.
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
public void setLeadingComponent( Component leadingComponent ) {
|
||||||
|
putClientProperty( TEXT_FIELD_LEADING_COMPONENT, leadingComponent );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a component that will be placed at the trailing edge of the text field.
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
public Component getTrailingComponent() {
|
||||||
|
return (Component) getClientProperty( TEXT_FIELD_TRAILING_COMPONENT );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies a component that will be placed at the trailing edge of the text field.
|
||||||
|
* <p>
|
||||||
|
* The component will be positioned inside and aligned to the visible text field border.
|
||||||
|
* There is no gap between the visible border and the component.
|
||||||
|
* The laid out component size will be the preferred component width
|
||||||
|
* and the inner text field height.
|
||||||
|
* <p>
|
||||||
|
* The component should be not opaque because the text field border is painted
|
||||||
|
* slightly inside the usually visible border in some cases.
|
||||||
|
* E.g. when focused (in some themes) or when an outline color is specified
|
||||||
|
* (see {@link #setOutline(Object)}.
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
public void setTrailingComponent( Component trailingComponent ) {
|
||||||
|
putClientProperty( TEXT_FIELD_TRAILING_COMPONENT, trailingComponent );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether all text is selected when the text component gains focus.
|
* Returns whether all text is selected when the text component gains focus.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.formdev.flatlaf.extras.components;
|
|||||||
|
|
||||||
import static com.formdev.flatlaf.FlatClientProperties.*;
|
import static com.formdev.flatlaf.FlatClientProperties.*;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.JTextField;
|
import javax.swing.JTextField;
|
||||||
@@ -84,6 +85,64 @@ public class FlatTextField
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a component that will be placed at the leading edge of the text field.
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
public Component getLeadingComponent() {
|
||||||
|
return (Component) getClientProperty( TEXT_FIELD_LEADING_COMPONENT );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies a component that will be placed at the leading edge of the text field.
|
||||||
|
* <p>
|
||||||
|
* The component will be positioned inside and aligned to the visible text field border.
|
||||||
|
* There is no gap between the visible border and the component.
|
||||||
|
* The laid out component size will be the preferred component width
|
||||||
|
* and the inner text field height.
|
||||||
|
* <p>
|
||||||
|
* The component should be not opaque because the text field border is painted
|
||||||
|
* slightly inside the usually visible border in some cases.
|
||||||
|
* E.g. when focused (in some themes) or when an outline color is specified
|
||||||
|
* (see {@link #setOutline(Object)}.
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
public void setLeadingComponent( Component leadingComponent ) {
|
||||||
|
putClientProperty( TEXT_FIELD_LEADING_COMPONENT, leadingComponent );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a component that will be placed at the trailing edge of the text field.
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
public Component getTrailingComponent() {
|
||||||
|
return (Component) getClientProperty( TEXT_FIELD_TRAILING_COMPONENT );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies a component that will be placed at the trailing edge of the text field.
|
||||||
|
* <p>
|
||||||
|
* The component will be positioned inside and aligned to the visible text field border.
|
||||||
|
* There is no gap between the visible border and the component.
|
||||||
|
* The laid out component size will be the preferred component width
|
||||||
|
* and the inner text field height.
|
||||||
|
* <p>
|
||||||
|
* The component should be not opaque because the text field border is painted
|
||||||
|
* slightly inside the usually visible border in some cases.
|
||||||
|
* E.g. when focused (in some themes) or when an outline color is specified
|
||||||
|
* (see {@link #setOutline(Object)}.
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
public void setTrailingComponent( Component trailingComponent ) {
|
||||||
|
putClientProperty( TEXT_FIELD_TRAILING_COMPONENT, trailingComponent );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// NOTE: enum names must be equal to allowed strings
|
// NOTE: enum names must be equal to allowed strings
|
||||||
public enum SelectAllOnFocusPolicy { never, once, always };
|
public enum SelectAllOnFocusPolicy { never, once, always };
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import java.awt.Component;
|
|||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
|
import java.util.function.Supplier;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.border.*;
|
import javax.swing.border.*;
|
||||||
import javax.swing.text.DefaultEditorKit;
|
import javax.swing.text.DefaultEditorKit;
|
||||||
@@ -58,26 +59,54 @@ public class FlatTextComponentsTest
|
|||||||
if( padding.equals( new Insets( 0, 0, 0, 0 ) ) )
|
if( padding.equals( new Insets( 0, 0, 0, 0 ) ) )
|
||||||
padding = null;
|
padding = null;
|
||||||
|
|
||||||
for( Component c : getComponents() ) {
|
putTextFieldClientProperty( FlatClientProperties.TEXT_FIELD_PADDING, padding );
|
||||||
if( c instanceof JTextField )
|
|
||||||
((JTextField)c).putClientProperty( FlatClientProperties.TEXT_FIELD_PADDING, padding );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void leadingIcon() {
|
private void leadingIcon() {
|
||||||
applyIcon( FlatClientProperties.TEXT_FIELD_LEADING_ICON, leadingIconCheckBox.isSelected()
|
putTextFieldClientProperty( FlatClientProperties.TEXT_FIELD_LEADING_ICON, leadingIconCheckBox.isSelected()
|
||||||
? new TestIcon( 8, 16, Color.blue ) : null );
|
? new TestIcon( 8, 16, Color.blue ) : null );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void trailingIcon() {
|
private void trailingIcon() {
|
||||||
applyIcon( FlatClientProperties.TEXT_FIELD_TRAILING_ICON, trailingIconCheckBox.isSelected()
|
putTextFieldClientProperty( FlatClientProperties.TEXT_FIELD_TRAILING_ICON, trailingIconCheckBox.isSelected()
|
||||||
? new TestIcon( 24, 12, Color.magenta ) : null );
|
? new TestIcon( 24, 12, Color.magenta ) : null );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyIcon( String key, Icon icon ) {
|
private void leadingComponent() {
|
||||||
|
putTextFieldClientProperty( FlatClientProperties.TEXT_FIELD_LEADING_COMPONENT, () -> {
|
||||||
|
if( !leadingComponentCheckBox.isSelected() )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
JLabel l = new JLabel( "lead" );
|
||||||
|
l.setOpaque( true );
|
||||||
|
l.setBackground( Color.green );
|
||||||
|
return l;
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void trailingComponent() {
|
||||||
|
putTextFieldClientProperty( FlatClientProperties.TEXT_FIELD_TRAILING_COMPONENT, () -> {
|
||||||
|
if( !trailingComponentCheckBox.isSelected() )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
JLabel l = new JLabel( "tr" );
|
||||||
|
l.setOpaque( true );
|
||||||
|
l.setBackground( Color.magenta );
|
||||||
|
return l;
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void putTextFieldClientProperty( String key, Object value ) {
|
||||||
for( Component c : getComponents() ) {
|
for( Component c : getComponents() ) {
|
||||||
if( c instanceof JTextField )
|
if( c instanceof JTextField )
|
||||||
((JTextField)c).putClientProperty( key, icon );
|
((JTextField)c).putClientProperty( key, value );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void putTextFieldClientProperty( String key, Supplier<Component> value ) {
|
||||||
|
for( Component c : getComponents() ) {
|
||||||
|
if( c instanceof JTextField )
|
||||||
|
((JTextField)c).putClientProperty( key, value.get() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,6 +139,8 @@ public class FlatTextComponentsTest
|
|||||||
bottomPaddingField = new JSpinner();
|
bottomPaddingField = new JSpinner();
|
||||||
leadingIconCheckBox = new JCheckBox();
|
leadingIconCheckBox = new JCheckBox();
|
||||||
trailingIconCheckBox = new JCheckBox();
|
trailingIconCheckBox = new JCheckBox();
|
||||||
|
leadingComponentCheckBox = new JCheckBox();
|
||||||
|
trailingComponentCheckBox = new JCheckBox();
|
||||||
JLabel passwordFieldLabel = new JLabel();
|
JLabel passwordFieldLabel = new JLabel();
|
||||||
JPasswordField passwordField1 = new JPasswordField();
|
JPasswordField passwordField1 = new JPasswordField();
|
||||||
JPasswordField passwordField3 = new JPasswordField();
|
JPasswordField passwordField3 = new JPasswordField();
|
||||||
@@ -256,7 +287,9 @@ public class FlatTextComponentsTest
|
|||||||
"[]" +
|
"[]" +
|
||||||
"[]" +
|
"[]" +
|
||||||
"[]" +
|
"[]" +
|
||||||
|
"[]0" +
|
||||||
"[]" +
|
"[]" +
|
||||||
|
"[]0" +
|
||||||
"[]"));
|
"[]"));
|
||||||
|
|
||||||
//---- button1 ----
|
//---- button1 ----
|
||||||
@@ -316,6 +349,18 @@ public class FlatTextComponentsTest
|
|||||||
trailingIconCheckBox.setName("trailingIconCheckBox");
|
trailingIconCheckBox.setName("trailingIconCheckBox");
|
||||||
trailingIconCheckBox.addActionListener(e -> trailingIcon());
|
trailingIconCheckBox.addActionListener(e -> trailingIcon());
|
||||||
panel1.add(trailingIconCheckBox, "cell 0 6 2 1,alignx left,growx 0");
|
panel1.add(trailingIconCheckBox, "cell 0 6 2 1,alignx left,growx 0");
|
||||||
|
|
||||||
|
//---- leadingComponentCheckBox ----
|
||||||
|
leadingComponentCheckBox.setText("leading component");
|
||||||
|
leadingComponentCheckBox.setName("leadingComponentCheckBox");
|
||||||
|
leadingComponentCheckBox.addActionListener(e -> leadingComponent());
|
||||||
|
panel1.add(leadingComponentCheckBox, "cell 0 7 2 1,alignx left,growx 0");
|
||||||
|
|
||||||
|
//---- trailingComponentCheckBox ----
|
||||||
|
trailingComponentCheckBox.setText("trailing component");
|
||||||
|
trailingComponentCheckBox.setName("trailingComponentCheckBox");
|
||||||
|
trailingComponentCheckBox.addActionListener(e -> trailingComponent());
|
||||||
|
panel1.add(trailingComponentCheckBox, "cell 0 8 2 1,alignx left,growx 0");
|
||||||
}
|
}
|
||||||
add(panel1, "cell 4 0 1 6,aligny top,growy 0");
|
add(panel1, "cell 4 0 1 6,aligny top,growy 0");
|
||||||
|
|
||||||
@@ -627,6 +672,8 @@ public class FlatTextComponentsTest
|
|||||||
private JSpinner bottomPaddingField;
|
private JSpinner bottomPaddingField;
|
||||||
private JCheckBox leadingIconCheckBox;
|
private JCheckBox leadingIconCheckBox;
|
||||||
private JCheckBox trailingIconCheckBox;
|
private JCheckBox trailingIconCheckBox;
|
||||||
|
private JCheckBox leadingComponentCheckBox;
|
||||||
|
private JCheckBox trailingComponentCheckBox;
|
||||||
private JTextField textField;
|
private JTextField textField;
|
||||||
private JCheckBox dragEnabledCheckBox;
|
private JCheckBox dragEnabledCheckBox;
|
||||||
private JTextArea textArea;
|
private JTextArea textArea;
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ new FormModel {
|
|||||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||||
"$layoutConstraints": "hidemode 3"
|
"$layoutConstraints": "hidemode 3"
|
||||||
"$columnConstraints": "[fill][fill]"
|
"$columnConstraints": "[fill][fill]"
|
||||||
"$rowConstraints": "[][][][][][][]"
|
"$rowConstraints": "[][][][][][]0[][]0[]"
|
||||||
} ) {
|
} ) {
|
||||||
name: "panel1"
|
name: "panel1"
|
||||||
"border": new javax.swing.border.TitledBorder( "Control" )
|
"border": new javax.swing.border.TitledBorder( "Control" )
|
||||||
@@ -168,6 +168,26 @@ new FormModel {
|
|||||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
"value": "cell 0 6 2 1,alignx left,growx 0"
|
"value": "cell 0 6 2 1,alignx left,growx 0"
|
||||||
} )
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||||
|
name: "leadingComponentCheckBox"
|
||||||
|
"text": "leading component"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "leadingComponent", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 7 2 1,alignx left,growx 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||||
|
name: "trailingComponentCheckBox"
|
||||||
|
"text": "trailing component"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "trailingComponent", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 8 2 1,alignx left,growx 0"
|
||||||
|
} )
|
||||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
"value": "cell 4 0 1 6,aligny top,growy 0"
|
"value": "cell 4 0 1 6,aligny top,growy 0"
|
||||||
} )
|
} )
|
||||||
|
|||||||
Reference in New Issue
Block a user