Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rounding for jTextArea #594

Closed
ViktorTrojan opened this issue Sep 25, 2022 · 8 comments
Closed

Rounding for jTextArea #594

ViktorTrojan opened this issue Sep 25, 2022 · 8 comments
Milestone

Comments

@ViktorTrojan
Copy link

Hey I wondered if you could add an option to round the jTextArea?

@DevCharly
Copy link
Collaborator

If the JTextArea is in a JScrollPane ?

@ViktorTrojan
Copy link
Author

If the JTextArea is in a JScrollPane ?

It is but I dont know any way to round a JScrollPane

@mlaggner
Copy link

As far as I see this heavily depends whether you embed the JTextArea into a scrollbar or not.

If it is embedded, you need to put the FlatTextBorder on the JScrollPane (which results all scrollpanes to use this border - but in my tests, I did not see this border for JTables or JLists).

If it is not embedded, you need to put the FlatTextBorder on the JTextArea

At the moment I am unsure how to handle mixing this without using component properties...

@mlaggner
Copy link

looks like rounded JScrollPane contents are rather complicated, because the viewport draws the clipped part into the corners (at least this is what I found out while trying to implement that).

I hope @DevCharly has a better idea how to solve that

@mlaggner
Copy link

mlaggner commented Mar 6, 2023

I found a workaround by creating a new component for a JTextArea (mostly by merging code from the UI for JTextArea and JTextField) which is not inside a JScrollPane:

public class RoundTextArea extends JTextArea {

  private static final String uiClassID = "RoundTextAreaUI";

  public TmmRoundTextArea() {
    super();
    setLineWrap(true);
    setWrapStyleWord(true);
  }

  public TmmRoundTextArea(String text) {
    super(text);
    setLineWrap(true);
    setWrapStyleWord(true);
  }

  /**
   * Returns the class ID for the UI.
   *
   * @return the string "TextAreaUI"
   * @see JComponent#getUIClassID
   * @see UIDefaults#getUI
   */
  @Override
  @BeanProperty(bound = false)
  public String getUIClassID() {
    return uiClassID;
  }
}
public class RoundTextAreaUI extends FlatTextAreaUI {

  private FocusListener focusListener;
  private DocumentListener documentListener;


  public static ComponentUI createUI(JComponent c) {
    return new TmmRoundTextAreaUI();
  }

  @Override
  protected void installDefaults() {
    super.installDefaults();

    LookAndFeel.installProperty(getComponent(), "opaque", false);
    getComponent().setBorder(new FlatTextBorder());
  }

  @Override
  protected void installListeners() {
    super.installListeners();

    // necessary to update focus border and background
    focusListener = new FlatUIUtils.RepaintFocusListener( getComponent(), null );
    getComponent().addFocusListener( focusListener );
  }

  @Override
  protected void uninstallListeners() {
    super.uninstallListeners();

    getComponent().removeFocusListener( focusListener );
    focusListener = null;

    if( documentListener != null ) {
      getComponent().getDocument().removeDocumentListener( documentListener );
      documentListener = null;
    }
  }

  @Override
  protected void paintSafely(Graphics g) {
    paintBackground(g, getComponent(), isIntelliJTheme, focusedBackground);
    super.paintSafely(g);
  }

  @Override
  protected void paintBackground(Graphics g) {
    // painted somehere else
  }

  static void paintBackground(Graphics g, JTextComponent c, boolean isIntelliJTheme, Color focusedBackground) {
    // do not paint background if:
    // - not opaque and
    // - border is not a flat border and
    // - opaque was explicitly set (to false)
    // (same behavior as in AquaTextFieldUI)
    if (!c.isOpaque() && FlatUIUtils.getOutsideFlatBorder(c) == null && FlatUIUtils.hasOpaqueBeenExplicitlySet(c)) {
      return;
    }

    float focusWidth = FlatUIUtils.getBorderFocusWidth(c);
    float arc = FlatUIUtils.getBorderArc(c);

    // fill background if opaque to avoid garbage if user sets opaque to true
    if (c.isOpaque() && (focusWidth > 0 || arc > 0)) {
      FlatUIUtils.paintParentBackground(g, c);
    }

    // paint background
    Graphics2D g2 = (Graphics2D) g.create();
    try {
      FlatUIUtils.setRenderingHints(g2);

      g2.setColor(getBackground(c, isIntelliJTheme, focusedBackground));
      FlatUIUtils.paintComponentBackground(g2, 0, 0, c.getWidth(), c.getHeight(), focusWidth, arc);
    }
    finally {
      g2.dispose();
    }
  }

  private static Color getBackground(JTextComponent c, boolean isIntelliJTheme, Color focusedBackground) {
    Color background = c.getBackground();

    // always use explicitly set color
    if (!(background instanceof UIResource)) {
      return background;
    }

    // focused
    if (focusedBackground != null && FlatUIUtils.isPermanentFocusOwner(c)) {
      return focusedBackground;
    }

    // for compatibility with IntelliJ themes
    if (isIntelliJTheme && (!c.isEnabled() || !c.isEditable())) {
      return FlatUIUtils.getParentBackground(c);
    }

    return background;
  }
}

and register that to FlatLaf:

RoundTextAreaUI=x.y.z.RoundTextAreaUI

I know this is rather hacky, but at least that works for my use case

@DevCharly
Copy link
Collaborator

There is now a draft PR for rounded scrollpanes. See PR #713.

@mlaggner
Copy link

looks promising. When will this be available in the FlatLaf release?

@DevCharly
Copy link
Collaborator

implemented in latest 3.3-SNAPSHOT: https://github.com/JFormDesigner/FlatLaf#snapshots

@DevCharly DevCharly added this to the 3.3 milestone Dec 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants