Browse Source

Merge pull request #39 from weisJ/text_demo

Demo & Fixes for JTextField/JPasswordField
pull/42/head
Jannis Weis 5 years ago committed by GitHub
parent
commit
2c2f961c71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      core/src/main/java/com/github/weisj/darklaf/ui/colorchooser/ColorValueFormatter.java
  2. 4
      core/src/main/java/com/github/weisj/darklaf/ui/text/DarkFormattedTextFieldUI.java
  3. 21
      core/src/main/java/com/github/weisj/darklaf/ui/text/DarkPasswordFieldUI.java
  4. 71
      core/src/main/java/com/github/weisj/darklaf/ui/text/DarkTextBorder.java
  5. 18
      core/src/main/java/com/github/weisj/darklaf/ui/text/DarkTextFieldUI.java
  6. 9
      core/src/main/java/com/github/weisj/darklaf/ui/text/DarkTextUI.java
  7. 9
      core/src/main/java/com/github/weisj/darklaf/util/DarkUIUtil.java
  8. 4
      core/src/main/resources/com/github/weisj/darklaf/properties/ui/spinner.properties
  9. 2
      core/src/main/resources/com/github/weisj/darklaf/properties/ui/tabbedPane.properties
  10. 2
      core/src/test/java/UIDemo.java
  11. 5
      core/src/test/java/ui/text/EditorPaneDemo.java
  12. 74
      core/src/test/java/ui/text/PasswordFieldDemo.java
  13. 5
      core/src/test/java/ui/text/TextAreaDemo.java
  14. 11
      core/src/test/java/ui/text/TextComponentDemo.java
  15. 74
      core/src/test/java/ui/text/TextFieldDemo.java
  16. 5
      core/src/test/java/ui/text/TextPaneDemo.java

6
core/src/main/java/com/github/weisj/darklaf/ui/colorchooser/ColorValueFormatter.java

@ -116,19 +116,19 @@ public final class ColorValueFormatter extends JFormattedTextField.AbstractForma
}
protected void error() {
text.putClientProperty("JTextField.hasError", true);
text.putClientProperty("JTextComponent.hasError", true);
text.repaint();
errorTimer.restart();
}
@Override
public void actionPerformed(final ActionEvent e) {
text.putClientProperty("JTextField.hasError", false);
text.putClientProperty("JTextComponent.hasError", false);
text.repaint();
}
private void commit() {
text.putClientProperty("JTextField.hasError", false);
text.putClientProperty("JTextComponent.hasError", false);
text.repaint();
SwingUtilities.invokeLater(() -> {
try {

4
core/src/main/java/com/github/weisj/darklaf/ui/text/DarkFormattedTextFieldUI.java

@ -99,9 +99,9 @@ public class DarkFormattedTextFieldUI extends DarkTextFieldUI implements Propert
if (textField == null) return;
try {
textField.getFormatter().stringToValue(textField.getText());
textField.putClientProperty("JTextField.hasError", false);
textField.putClientProperty("JTextComponent.hasError", false);
} catch (ParseException e) {
textField.putClientProperty("JTextField.hasError", true);
textField.putClientProperty("JTextComponent.hasError", true);
}
}
}

21
core/src/main/java/com/github/weisj/darklaf/ui/text/DarkPasswordFieldUI.java

@ -33,6 +33,7 @@ import javax.swing.plaf.ComponentUI;
import javax.swing.text.JTextComponent;
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.util.Arrays;
/**
@ -178,15 +179,15 @@ public class DarkPasswordFieldUI extends DarkPasswordFieldUIBridge {
public static boolean hasShowIcon(final Component c) {
return c instanceof JPasswordField
&& Boolean.TRUE.equals(((JComponent) c).getClientProperty("PasswordField.view"));
&& Boolean.TRUE.equals(((JComponent) c).getClientProperty("JPasswordField.showViewIcon"));
}
private Point getShowIconCoord() {
Rectangle r = getDrawingRect(getComponent());
int w = getShowIcon().getIconWidth();
Insets ins = DarkUIUtil.getBorderInsets(editor);
return new Point(r.x + r.width - w - ins.left, r.y + (r.height - w) / 2);
return DarkUIUtil.adjustForOrientation(new Point(r.x + r.width - w - borderSize, r.y + (r.height - w) / 2),
w, editor);
}
private boolean isOverEye(final Point p) {
@ -212,4 +213,18 @@ public class DarkPasswordFieldUI extends DarkPasswordFieldUIBridge {
echo_dot = ((JPasswordField) c).getEchoChar();
}
}
@Override
public void propertyChange(final PropertyChangeEvent evt) {
super.propertyChange(evt);
String key = evt.getPropertyName();
if ("JPasswordField.showViewIcon".equals(key)) {
editor.doLayout();
Component parent = editor.getParent();
if (parent instanceof JComponent) {
parent.doLayout();
}
editor.repaint();
}
}
}

71
core/src/main/java/com/github/weisj/darklaf/ui/text/DarkTextBorder.java

@ -68,6 +68,37 @@ public class DarkTextBorder implements Border, UIResource {
showIcon = UIManager.getIcon("PasswordField.show.icon");
}
protected static boolean hasError(final Component c) {
return c instanceof JComponent
&& Boolean.TRUE.equals(((JComponent) c).getClientProperty("JTextComponent.hasError"));
}
protected static boolean isCellEditor(final Component c) {
return c instanceof JComponent
&& Boolean.TRUE.equals(((JComponent) c).getClientProperty("JTextField.cellEditor"));
}
protected int getArcSize(final Component c) {
boolean alt = DarkTextFieldUI.chooseAlternativeArc(c);
if (!alt && !DarkTextFieldUI.isSearchField(c)) {
return 0;
}
return DarkTextFieldUI.isSearchField(c) ? (alt ? arc : searchArc) : (alt ? searchArc : arc);
}
protected int getFocusArcSize(final Component c) {
boolean alt = DarkTextFieldUI.chooseAlternativeArc(c);
if (!alt && !DarkTextFieldUI.isSearchField(c)) {
return minimumArc;
}
return DarkTextFieldUI.isSearchField(c) ? (alt ? arc : searchArc) : (alt ? searchArc : arc);
}
public int getBorderSize() {
return borderSize;
}
public void paintBorder(final Component c, final Graphics g2, final int x, final int y,
final int width, final int height) {
if (isCellEditor(c)) {
@ -98,7 +129,10 @@ public class DarkTextBorder implements Border, UIResource {
} else if (DarkTextFieldUI.isSearchField(c)) {
g.setColor(getBorderColor(c));
if (((JComponent) c).getClientProperty("JTextField.Search.noBorderRing") != Boolean.TRUE) {
if (c.hasFocus()) {
if (hasError(c)) {
DarkUIUtil.paintOutlineBorder(g, width, height, focusArcSize, borderSize,
c.hasFocus(), DarkUIUtil.Outline.error);
} else if (c.hasFocus()) {
DarkUIUtil.paintFocusBorder(g, width, height, arcSize, borderSize);
}
g.setColor(getBorderColor(c));
@ -110,37 +144,6 @@ public class DarkTextBorder implements Border, UIResource {
config.restore();
}
protected static boolean isCellEditor(final Component c) {
return c instanceof JComponent
&& Boolean.TRUE.equals(((JComponent) c).getClientProperty("JTextField.cellEditor"));
}
protected int getArcSize(final Component c) {
boolean alt = DarkTextFieldUI.chooseAlternativeArc(c);
if (!alt && !DarkTextFieldUI.isSearchField(c)) {
return 0;
}
return DarkTextFieldUI.isSearchField(c) ? (alt ? arc : searchArc) : (alt ? searchArc : arc);
}
protected int getFocusArcSize(final Component c) {
boolean alt = DarkTextFieldUI.chooseAlternativeArc(c);
if (!alt && !DarkTextFieldUI.isSearchField(c)) {
return minimumArc;
}
return DarkTextFieldUI.isSearchField(c) ? (alt ? arc : searchArc) : (alt ? searchArc : arc);
}
public int getBorderSize() {
return borderSize;
}
protected static boolean hasError(final Component c) {
return c instanceof JComponent
&& Boolean.TRUE.equals(((JComponent) c).getClientProperty("JTextField.hasError"));
}
protected Color getBorderColor(final Component c) {
boolean editable = !(c instanceof JTextComponent) || ((JTextComponent) c).isEditable();
boolean focus = DarkUIUtil.hasFocus(c);
@ -173,7 +176,11 @@ public class DarkTextBorder implements Border, UIResource {
insets.right += padding.right + clearWidth;
} else if (DarkPasswordFieldUI.hasShowIcon(c)) {
int eyeWidth = showIcon.getIconWidth();
if (c.getComponentOrientation().isLeftToRight()) {
insets.right += padding.right + eyeWidth;
} else {
insets.left += padding.left + eyeWidth;
}
}
return insets;
}

18
core/src/main/java/com/github/weisj/darklaf/ui/text/DarkTextFieldUI.java

@ -163,8 +163,8 @@ public class DarkTextFieldUI extends DarkTextFieldUIBridge implements PropertyCh
protected Point getSearchIconCoord() {
Rectangle r = getDrawingRect(getComponent());
int w = getSearchIcon(getComponent()).getIconWidth();
Insets ins = DarkUIUtil.getBorderInsets(editor);
return new Point(r.x + ins.left, r.y + (r.height - w) / 2);
return DarkUIUtil.adjustForOrientation(new Point(r.x + borderSize, r.y + (r.height - w) / 2),
w, editor);
}
protected static Icon getSearchIcon(final Component c) {
@ -227,10 +227,11 @@ public class DarkTextFieldUI extends DarkTextFieldUIBridge implements PropertyCh
protected Point getClearIconCoord() {
Rectangle r = getDrawingRect(getComponent());
int w = getClearIcon(clearHovered).getIconWidth();
Insets ins = DarkUIUtil.getBorderInsets(editor);
return new Point(r.x + r.width - w - ins.left, r.y + (r.height - w) / 2);
return DarkUIUtil.adjustForOrientation(new Point(r.x + r.width - w - borderSize, r.y + (r.height - w) / 2),
w, editor);
}
protected void showSearchPopup() {
if (lastSearchEvent == 0 || (System.currentTimeMillis() - lastSearchEvent) > 250) {
JPopupMenu menu = getSearchPopup(getComponent());
@ -257,11 +258,11 @@ public class DarkTextFieldUI extends DarkTextFieldUIBridge implements PropertyCh
clear = UIManager.getIcon("TextField.search.clear.icon");
searchWithHistory = UIManager.getIcon("TextField.search.searchWithHistory.icon");
search = UIManager.getIcon("TextField.search.search.icon");
}
@Override
public void propertyChange(final PropertyChangeEvent evt) {
super.propertyChange(evt);
String key = evt.getPropertyName();
if ("JTextField.Search.FindPopup".equals(key)) {
Object oldVal = evt.getOldValue();
@ -272,6 +273,13 @@ public class DarkTextFieldUI extends DarkTextFieldUIBridge implements PropertyCh
if (newVal instanceof JPopupMenu) {
((JPopupMenu) newVal).addPopupMenuListener(searchPopupListener);
}
} else if ("JTextField.variant".equals(key)) {
editor.doLayout();
Component parent = editor.getParent();
if (parent instanceof JComponent) {
parent.doLayout();
}
editor.repaint();
}
}

9
core/src/main/java/com/github/weisj/darklaf/ui/text/DarkTextUI.java

@ -36,12 +36,7 @@ import javax.swing.plaf.ActionMapUIResource;
import javax.swing.plaf.ComponentInputMapUIResource;
import javax.swing.plaf.InputMapUIResource;
import javax.swing.plaf.basic.BasicTextUI;
import javax.swing.text.Caret;
import javax.swing.text.DefaultEditorKit;
import javax.swing.text.EditorKit;
import javax.swing.text.Highlighter;
import javax.swing.text.JTextComponent;
import javax.swing.text.TextAction;
import javax.swing.text.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
@ -83,6 +78,8 @@ public abstract class DarkTextUI extends BasicTextUI implements PropertyChangeLi
String key = evt.getPropertyName();
if ("JTextComponent.roundedSelection".equals(key)) {
editor.repaint();
} else if ("JTextComponent.hasError".equals(key)) {
editor.repaint();
}
}

9
core/src/main/java/com/github/weisj/darklaf/util/DarkUIUtil.java

@ -82,7 +82,7 @@ public final class DarkUIUtil {
GraphicsContext context = GraphicsUtil.setupStrokePainting(g);
Shape outerRect = new RoundRectangle2D.Float(0, 0, width, height, arc + bw, arc + bw);
Shape innerRect = new RoundRectangle2D.Float(bw, bw, width - 2 * bw, height - 2 * bw, arc, arc);
Shape innerRect = new RoundRectangle2D.Float(bw, bw, width - 2 * bw, height - 2 * bw, arc - bw, arc - bw);
Path2D path = new Path2D.Float(Path2D.WIND_EVEN_ODD);
path.append(outerRect, false);
path.append(innerRect, false);
@ -354,6 +354,13 @@ public final class DarkUIUtil {
return border.getBorderInsets(comp);
}
public static Point adjustForOrientation(final Point p, final int w, final Component c) {
if (!c.getComponentOrientation().isLeftToRight()) {
p.x = c.getWidth() - p.x - w;
}
return p;
}
public enum Outline {
error {
@Override

4
core/src/main/resources/com/github/weisj/darklaf/properties/ui/spinner.properties

@ -38,8 +38,8 @@ Spinner.arrowButtonBorder = null
Spinner.arc = %arc
Spinner.borderThickness = %borderThickness
Spinner.cellEditorInsets = 2, 5, 2, 5
Spinner.insets = 7, 7, 7, 7
Spinner.cellEditorInsets = 2,5,2,5
Spinner.insets = 7,7,7,7
Spinner.plus.icon = misc/plus.svg[themed]
Spinner.plusInactive.icon = misc/plus.svg[themed]

2
core/src/main/resources/com/github/weisj/darklaf/properties/ui/tabbedPane.properties

@ -47,7 +47,7 @@ TabbedPane.tabsOverlapBorder = false
TabbedPane.labelShift = 0
TabbedPane.selectedLabelShift = 0
TabbedPane.selectedTabPadInsets = 0,0,0,0
TabbedPane.tabAreaInsets = 0,0,0,
TabbedPane.tabAreaInsets = 0,0,0,0
TabbedPane.newTabButton.insets = 2,2,2,2
TabbedPane.moreTabsButton.pad = 2

2
core/src/test/java/UIDemo.java

@ -152,7 +152,7 @@ public final class UIDemo {
add(new JPasswordField("Password"));
add(new JPasswordField("VeryStrongPassword") {{
putClientProperty("JTextField.alternativeArc", Boolean.TRUE);
putClientProperty("PasswordField.view", Boolean.TRUE);
putClientProperty("JPasswordField.showViewIcon", Boolean.TRUE);
}});
}});
panel.add(new JPanel() {{

5
core/src/test/java/ui/text/EditorPaneDemo.java

@ -26,16 +26,15 @@ package ui.text;
import ui.ComponentDemo;
import javax.swing.*;
import javax.swing.text.JTextComponent;
public class EditorPaneDemo extends TextComponentDemo {
public class EditorPaneDemo extends TextComponentDemo<JEditorPane> {
public static void main(final String[] args) {
ComponentDemo.showDemo(new EditorPaneDemo());
}
@Override
protected JTextComponent createTextComponent() {
protected JEditorPane createTextComponent() {
return new JEditorPane();
}

74
core/src/test/java/ui/text/PasswordFieldDemo.java

@ -0,0 +1,74 @@
/*
* MIT License
*
* Copyright (c) 2020 Jannis Weis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package ui.text;
import ui.ComponentDemo;
import ui.DemoPanel;
import javax.swing.*;
import java.awt.*;
public class PasswordFieldDemo implements ComponentDemo {
public static void main(final String[] args) {
ComponentDemo.showDemo(new PasswordFieldDemo());
}
@Override
public JComponent createComponent() {
JPasswordField textField = new JPasswordField("Demo PasswordField");
DemoPanel panel = new DemoPanel(textField);
JPanel controlPanel = panel.getControls();
controlPanel.setLayout(new GridLayout(3, 2));
controlPanel.add(new JCheckBox("enabled") {{
setSelected(textField.isEnabled());
addActionListener(e -> textField.setEnabled(isSelected()));
}});
controlPanel.add(new JCheckBox("editable") {{
setSelected(textField.isEditable());
addActionListener(e -> textField.setEditable(isSelected()));
}});
controlPanel.add(new JCheckBox("LeftToRight") {{
setEnabled(true);
addActionListener(e -> textField.setComponentOrientation(isSelected() ? ComponentOrientation.LEFT_TO_RIGHT
: ComponentOrientation.RIGHT_TO_LEFT));
}});
controlPanel.add(new JCheckBox("JTextComponent.roundedSelection") {{
setSelected(true);
addActionListener(e -> textField.putClientProperty("JTextComponent.roundedSelection", isSelected()));
}});
controlPanel.add(new JCheckBox("JPasswordField.showViewIcon") {{
addActionListener(e -> textField.putClientProperty("JPasswordField.showViewIcon", isSelected()));
}});
controlPanel.add(new JCheckBox("JTextComponent.hasError") {{
addActionListener(e -> textField.putClientProperty("JTextComponent.hasError", isSelected()));
}});
return panel;
}
@Override
public String getTitle() {
return "PasswordField Demo";
}
}

5
core/src/test/java/ui/text/TextAreaDemo.java

@ -26,16 +26,15 @@ package ui.text;
import ui.ComponentDemo;
import javax.swing.*;
import javax.swing.text.JTextComponent;
public class TextAreaDemo extends TextComponentDemo {
public class TextAreaDemo extends TextComponentDemo<JTextArea> {
public static void main(final String[] args) {
ComponentDemo.showDemo(new TextAreaDemo());
}
@Override
protected JTextComponent createTextComponent() {
protected JTextArea createTextComponent() {
return new JTextArea();
}

11
core/src/test/java/ui/text/TextComponentDemo.java

@ -33,18 +33,18 @@ import javax.swing.border.Border;
import javax.swing.text.JTextComponent;
import java.awt.*;
public abstract class TextComponentDemo implements ComponentDemo {
public abstract class TextComponentDemo<T extends JTextComponent> implements ComponentDemo {
@Override
public JComponent createComponent() {
JTextComponent text = createTextComponent();
T text = createTextComponent();
text.setText(StringUtil.repeat(StringUtil.repeat("Word ", 5) + "\n", 5));
DemoPanel panel = new DemoPanel(text);
Border textBorder = new DarkTextBorder();
Border border = text.getBorder();
JPanel controlPanel = panel.getControls();
controlPanel.setLayout(new GridLayout(2, 2));
controlPanel.setLayout(new GridLayout(3, 2));
controlPanel.add(new JCheckBox("enabled") {{
setSelected(text.isEnabled());
addActionListener(e -> text.setEnabled(isSelected()));
@ -61,8 +61,11 @@ public abstract class TextComponentDemo implements ComponentDemo {
setSelected(true);
addActionListener(e -> text.putClientProperty("JTextComponent.roundedSelection", isSelected()));
}});
controlPanel.add(new JCheckBox("JTextComponent.hasError") {{
addActionListener(e -> text.putClientProperty("JTextComponent.hasError", isSelected()));
}});
return panel;
}
protected abstract JTextComponent createTextComponent();
protected abstract T createTextComponent();
}

74
core/src/test/java/ui/text/TextFieldDemo.java

@ -0,0 +1,74 @@
/*
* MIT License
*
* Copyright (c) 2020 Jannis Weis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package ui.text;
import ui.ComponentDemo;
import ui.DemoPanel;
import javax.swing.*;
import java.awt.*;
public class TextFieldDemo implements ComponentDemo {
public static void main(final String[] args) {
ComponentDemo.showDemo(new TextFieldDemo());
}
@Override
public JComponent createComponent() {
JTextField textField = new JTextField("Demo TextField");
DemoPanel panel = new DemoPanel(textField);
JPanel controlPanel = panel.getControls();
controlPanel.setLayout(new GridLayout(3, 2));
controlPanel.add(new JCheckBox("enabled") {{
setSelected(textField.isEnabled());
addActionListener(e -> textField.setEnabled(isSelected()));
}});
controlPanel.add(new JCheckBox("editable") {{
setSelected(textField.isEditable());
addActionListener(e -> textField.setEditable(isSelected()));
}});
controlPanel.add(new JCheckBox("LeftToRight") {{
setEnabled(true);
addActionListener(e -> textField.setComponentOrientation(isSelected() ? ComponentOrientation.LEFT_TO_RIGHT
: ComponentOrientation.RIGHT_TO_LEFT));
}});
controlPanel.add(new JCheckBox("JTextComponent.roundedSelection") {{
setSelected(true);
addActionListener(e -> textField.putClientProperty("JTextComponent.roundedSelection", isSelected()));
}});
controlPanel.add(new JCheckBox("JTextField.variant = search") {{
addActionListener(e -> textField.putClientProperty("JTextField.variant", isSelected() ? "search" : ""));
}});
controlPanel.add(new JCheckBox("JTextComponent.hasError") {{
addActionListener(e -> textField.putClientProperty("JTextComponent.hasError", isSelected()));
}});
return panel;
}
@Override
public String getTitle() {
return "TextField Demo";
}
}

5
core/src/test/java/ui/text/TextPaneDemo.java

@ -26,16 +26,15 @@ package ui.text;
import ui.ComponentDemo;
import javax.swing.*;
import javax.swing.text.JTextComponent;
public class TextPaneDemo extends TextComponentDemo {
public class TextPaneDemo extends TextComponentDemo<JTextPane> {
public static void main(final String[] args) {
ComponentDemo.showDemo(new TextPaneDemo());
}
@Override
protected JTextComponent createTextComponent() {
protected JTextPane createTextComponent() {
return new JTextPane();
}

Loading…
Cancel
Save