Browse Source

REPORT-111995 修复三态复选框

newui
Levy.Xie-解安森 12 months ago
parent
commit
43842743f1
  1. 1
      designer-base/src/main/java/com/fr/design/gui/itree/checkboxtree/NullTristateCheckBox.java
  2. 108
      designer-base/src/main/java/com/fr/design/gui/itree/checkboxtree/TristateCheckBox.java
  3. 43
      designer-base/src/test/java/com/fr/design/gui/storybook/components/CheckBoxStoryBoard.java

1
designer-base/src/main/java/com/fr/design/gui/itree/checkboxtree/NullTristateCheckBox.java

@ -62,6 +62,7 @@ public class NullTristateCheckBox extends TristateCheckBox {
@Override
public void updateUI() {
super.updateUI();
clearAttribute();
}

108
designer-base/src/main/java/com/fr/design/gui/itree/checkboxtree/TristateCheckBox.java

@ -1,33 +1,17 @@
package com.fr.design.gui.itree.checkboxtree;
import com.fr.design.constants.UIConstants;
import com.fine.theme.icon.LazyIcon;
import com.fr.design.event.StateChangeListener;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.utils.gui.GUIPaintUtils;
import com.fr.stable.Constants;
import sun.swing.SwingUtilities2;
import javax.swing.AbstractAction;
import javax.swing.AbstractButton;
import javax.swing.ActionMap;
import javax.swing.ButtonGroup;
import javax.swing.ButtonModel;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.ActionMapUIResource;
import javax.swing.plaf.basic.BasicHTML;
import javax.swing.plaf.metal.MetalCheckBoxUI;
import javax.swing.text.View;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemListener;
@ -54,6 +38,7 @@ import java.awt.event.MouseListener;
* @author Dr. Heinz M. Kabutz
*/
public class TristateCheckBox extends UICheckBox {
/**
* This is a type-safe enumerated type
*/
@ -80,7 +65,6 @@ public class TristateCheckBox extends UICheckBox {
public TristateCheckBox(String text, Icon icon, State initial) {
super(text, icon);
setUI(new TristateCheckBoxUI());
// Add a listener for when the mouse is pressed
super.addMouseListener(new MouseAdapter() {
@Override
@ -106,19 +90,21 @@ public class TristateCheckBox extends UICheckBox {
setState(initial);
}
@Override
public Icon getSelectedIcon() {
return getState() == DO_NOT_CARE ? new LazyIcon("checkbox_part_checked") : super.getSelectedIcon();
}
public TristateCheckBox(String text, State initial) {
this(text, null, initial);
setUI(new TristateCheckBoxUI());
}
public TristateCheckBox(String text) {
this(text, DO_NOT_CARE);
setUI(new TristateCheckBoxUI());
}
public TristateCheckBox() {
this(null);
setUI(new TristateCheckBoxUI());
}
/**
@ -359,84 +345,4 @@ public class TristateCheckBox extends UICheckBox {
}
}
private class TristateCheckBoxUI extends MetalCheckBoxUI {
@Override
public void paint(Graphics g, JComponent c) {
synchronized (this) {
AbstractButton b = (AbstractButton) c;
ButtonModel model = b.getModel();
Dimension size = c.getSize();
Font f = c.getFont();
g.setFont(f);
FontMetrics fm = SwingUtilities2.getFontMetrics(c, g, f);
Rectangle viewRect = new Rectangle(size);
Rectangle iconRect = new Rectangle();
Rectangle textRect = new Rectangle();
Insets i = c.getInsets();
viewRect.x += i.left;
viewRect.y += i.top;
viewRect.width -= (i.right + viewRect.x);
viewRect.height -= (i.bottom + viewRect.y);
Icon altIcon = b.getIcon();
String text = SwingUtilities.layoutCompoundLabel(
c, fm, b.getText(), altIcon != null ? altIcon : getDefaultIcon(),
b.getVerticalAlignment(), b.getHorizontalAlignment(),
b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
viewRect, iconRect, textRect, b.getIconTextGap());
// fill background
if (c.isOpaque()) {
g.setColor(b.getBackground());
g.fillRect(0, 0, size.width, size.height);
}
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if (SELECTED.equals(getState())) {
GUIPaintUtils.fillPaint(g2d, iconRect.x, iconRect.y, iconRect.width, iconRect.height, false, Constants.NULL,
model.isEnabled() ? UIConstants.CHECKBOX_HOVER_SELECTED : UIConstants.DISABLED_ICON_COLOR, 0);
} else if (model.isRollover() && !SELECTED.equals(getState())) {
g.setColor(UIConstants.CHECKBOX_HOVER_SELECTED);
g2d.drawRoundRect(iconRect.x, iconRect.y, iconRect.width - 1, iconRect.height - 1, UIConstants.ARC, UIConstants.ARC);
} else {
g.setColor(UIConstants.LINE_COLOR);
g2d.drawRoundRect(iconRect.x, iconRect.y, iconRect.width - 1, iconRect.height - 1, UIConstants.ARC, UIConstants.ARC);
}
if (SELECTED.equals(getState())) {
UIConstants.YES_ICON.paintIcon(c, g, iconRect.x + 2, iconRect.y + 2);
} else if (DO_NOT_CARE.equals(getState())) {
g.setColor(UIConstants.CHECKBOX_HOVER_SELECTED);
g2d.fillRoundRect(iconRect.x + 2, iconRect.y + 2, iconRect.width - 4, iconRect.height - 4, UIConstants.ARC, UIConstants.ARC);
}
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
// Draw the Text
drawLine(text, g, b, c, textRect, fm);
}
}
private void drawLine(String text, Graphics g, AbstractButton b, JComponent c, Rectangle textRect, FontMetrics fm) {
if (text != null) {
View v = (View) c.getClientProperty(BasicHTML.propertyKey);
if (v != null) {
v.paint(g, textRect);
} else {
int mnemIndex = b.getDisplayedMnemonicIndex();
if (model.isEnabled()) {
g.setColor(b.getForeground());
} else {
g.setColor(getDisabledTextColor());
}
SwingUtilities2.drawStringUnderlineCharAt(c, g, text,
mnemIndex, textRect.x, textRect.y + fm.getAscent());
}
}
}
}
}

43
designer-base/src/test/java/com/fr/design/gui/storybook/components/CheckBoxStoryBoard.java

@ -3,10 +3,17 @@ package com.fr.design.gui.storybook.components;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itree.checkboxtree.NullTristateCheckBox;
import com.fr.design.gui.itree.checkboxtree.TristateCheckBox;
import com.fr.design.gui.storybook.Story;
import com.fr.design.gui.storybook.StoryBoard;
import javax.swing.AbstractButton;
import javax.swing.JPanel;
import java.awt.Component;
import java.awt.event.ItemListener;
import java.util.Arrays;
import java.util.List;
import static com.fine.swing.ui.layout.Layouts.cell;
import static com.fine.swing.ui.layout.Layouts.column;
@ -46,10 +53,46 @@ public class CheckBoxStoryBoard extends StoryBoard {
cell(getDisabledStatus(new UICheckBox("测试"))),
cell(getDisabledSelectedStatus(new UICheckBox("测试")))
),
cell(new UILabel("三态选择框")).with(this::h3),
row(10,
cell(initTristateCheckboxGroup())
),
flex()
);
}
private JPanel initTristateCheckboxGroup() {
TristateCheckBox parent = new NullTristateCheckBox("父选框", TristateCheckBox.NOT_SELECTED);
UICheckBox checkBoxA = new UICheckBox("子选框1");
UICheckBox checkBoxB = new UICheckBox("子选框1");
UICheckBox checkBoxC = new UICheckBox("子选框1");
List<UICheckBox> childBoxes = Arrays.asList(checkBoxA, checkBoxB, checkBoxC);
ItemListener sonListener = e -> {
int selectedCount = (int) childBoxes.stream().filter(AbstractButton::isSelected).count();
if (selectedCount == 0) {
parent.setState(TristateCheckBox.NOT_SELECTED);
} else if (selectedCount == childBoxes.size()) {
parent.setState(TristateCheckBox.SELECTED);
} else {
parent.setState(TristateCheckBox.DO_NOT_CARE);
}
};
childBoxes.forEach(it -> it.addItemListener(sonListener));
parent.addStateChangeListener(() -> {
childBoxes.forEach(it -> it.removeItemListener(sonListener));
if (parent.getState() == TristateCheckBox.SELECTED) {
childBoxes.forEach(it -> it.setSelected(true));
} else if (parent.getState() == TristateCheckBox.NOT_SELECTED) {
childBoxes.forEach(it -> it.setSelected(false));
}
childBoxes.forEach(it -> it.addItemListener(sonListener));
});
return row(10,
cell(parent), cell(checkBoxA), cell(checkBoxB), cell(checkBoxC)
).getComponent();
}
private Component getDisabledStatus(UICheckBox c) {
c.setEnabled(false);
return c;

Loading…
Cancel
Save