diff --git a/designer-base/src/main/java/com/fine/theme/light/ui/FineCalendarPaneUI.java b/designer-base/src/main/java/com/fine/theme/light/ui/FineCalendarPaneUI.java new file mode 100644 index 0000000000..5edfa07bbc --- /dev/null +++ b/designer-base/src/main/java/com/fine/theme/light/ui/FineCalendarPaneUI.java @@ -0,0 +1,161 @@ +package com.fine.theme.light.ui; + +import com.fine.theme.utils.FineUIScale; +import com.formdev.flatlaf.ui.FlatRoundBorder; +import com.formdev.flatlaf.ui.FlatUIUtils; +import com.fr.design.gui.date.UICalendarPanel; +import com.fr.design.gui.date.UIDayLabel; + +import javax.swing.JComponent; +import javax.swing.UIManager; +import javax.swing.border.LineBorder; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.PanelUI; +import java.awt.Color; +import java.awt.Component; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; + + +/** + * {@link UICalendarPanel} 的 UI 样式 + * @author lemon + * @since 12.0 + * Created on 2024/09/22 + */ +public class FineCalendarPaneUI extends PanelUI { + protected Color defaultBackground; + protected Color selectedBackground; + protected Color hoverBackground; + protected Color pressedBackground; + protected Color otherMonthForeground; + + protected int arc; + + /** + * @param shared + * @since 2 + */ + protected FineCalendarPaneUI() { + super(); + } + + /** + * 创建UI + * + * @param c 组件 + * @return ComponentUI + */ + public static ComponentUI createUI(JComponent c) { + return FlatUIUtils.createSharedUI(FineCalendarPaneUI.class, FineCalendarPaneUI::new); + } + + /** + * + * @param c the component where this UI delegate is being installed + * + */ + public void installUI(JComponent c) { + super.installUI(c); + selectedBackground = UIManager.getColor("Calendar.day.selectedBackground"); + hoverBackground = UIManager.getColor("Calendar.day.hoverBackground"); + pressedBackground = UIManager.getColor("Calendar.day.pressedBackground"); + defaultBackground = UIManager.getColor("Calendar.background"); + otherMonthForeground = UIManager.getColor("Calendar.dayOtherMonth.foreground"); + + arc = UIManager.getInt("Calendar.day.arc"); + + //renderer this + c.setBackground(defaultBackground); + c.setBorder(new LineBorder(FlatUIUtils.getUIColor("defaultBorderColor", Color.BLACK))); + } + + @Override + public void uninstallUI(JComponent c) { + super.uninstallUI(c); + } + + /** + * UICalendarPanel paint, 目前只对 {@link UIDayLabel} 样式自定义,其余使用默认样式 + * @param g the Graphics context in which to paint + * @param c the component being painted; + * this argument is often ignored, + * but might be used if the UI object is stateless + * and shared by multiple components + * + */ + public void paint(Graphics g, JComponent c) { + if (c instanceof UICalendarPanel) { + UICalendarPanel calendar = (UICalendarPanel) c; + paintComponent(calendar); + } + } + + private void paintComponent(JComponent component) { + if (component instanceof UIDayLabel) { + paintDayLabel((UIDayLabel) component); + return; + } + for (Component c : component.getComponents()) { + paintComponent((JComponent) c); + } + } + + private void paintDayLabel(UIDayLabel label) { + if (!label.isSmallLabel()) { + return; + } + + label.setBorder(new DayLabelRoundedBorder()); + + if (!label.isCurrentMonth()) { + label.setForeground(otherMonthForeground); + } + } + + private Color getBackgroundColor(UIDayLabel dayLabel) { + if (dayLabel.isSelected()) { + return selectedBackground; + } + if (dayLabel.isHovered()) { + return hoverBackground; + } + if (dayLabel.isPressed()) { + return pressedBackground; + } + return defaultBackground; + } + + /** + * {@link UIDayLabel} 的 border 样式 + */ + private class DayLabelRoundedBorder extends FlatRoundBorder { + + public DayLabelRoundedBorder() { + } + + @Override + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + Graphics2D g2 = (Graphics2D)g.create(); + + try { + FlatUIUtils.setRenderingHints(g2); + g2.setColor(getBackgroundColor((UIDayLabel) c)); + g2.fillRoundRect(0, 0, width , height, arc, arc); + + // 避免文字被背景色覆盖 + UIDayLabel dayLabel = (UIDayLabel) c; + g2.setColor(dayLabel.getForeground()); + FontMetrics metrics = g2.getFontMetrics(dayLabel.getFont()); + int x1 = (width - metrics.stringWidth(dayLabel.getText())) / 2; + int y1 = ((height - metrics.getHeight()) / 2) + metrics.getAscent(); + g2.drawString(dayLabel.getText(), x1, y1); + } finally { + g2.dispose(); + } + } + + } + +} diff --git a/designer-base/src/main/java/com/fine/theme/light/ui/FineDayLabelUI.java b/designer-base/src/main/java/com/fine/theme/light/ui/FineDayLabelUI.java deleted file mode 100644 index ccd3ed8551..0000000000 --- a/designer-base/src/main/java/com/fine/theme/light/ui/FineDayLabelUI.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.fine.theme.light.ui; - - -import com.fr.design.gui.date.UIDayLabel; - -import javax.swing.AbstractButton; -import javax.swing.JComponent; -import javax.swing.UIManager; -import javax.swing.plaf.ComponentUI; -import java.awt.Color; - -/** - * {@link UIDayLabel} 的 UI 样式 - * @author lemon - * @since 12.0 - * Created on 2024/09/22 - */ -public class FineDayLabelUI extends FineButtonUI { - protected Color selectedBackground; - - /** - * @param shared - * @since 2 - */ - protected FineDayLabelUI(boolean shared) { - super(shared); - } - - /** - * 创建UI - * - * @param c 组件 - * @return ComponentUI - */ - public static ComponentUI createUI(JComponent c) { - return new FineDayLabelUI(false); - } - - @Override - protected void installDefaults(AbstractButton b) { - super.installDefaults(b); - selectedBackground = UIManager.getColor("Calendar.day.selectedBackground"); - } - - - @Override - protected Color getBackground(JComponent c) { - if (c instanceof UIDayLabel) { - return ((UIDayLabel) c).isSelected() ? selectedBackground : super.getBackground(c); - } - return super.getBackground(c); - } - -} diff --git a/designer-base/src/main/java/com/fr/design/gui/date/CalendarNumberField.java b/designer-base/src/main/java/com/fr/design/gui/date/CalendarNumberField.java index 454f3c525e..8b96c79db6 100644 --- a/designer-base/src/main/java/com/fr/design/gui/date/CalendarNumberField.java +++ b/designer-base/src/main/java/com/fr/design/gui/date/CalendarNumberField.java @@ -36,7 +36,6 @@ public class CalendarNumberField extends UINumberField { setValue(getIntValue()); } }); - this.setFont(DesignUtils.getDefaultGUIFont()); } public void setValue(int value) { diff --git a/designer-base/src/main/java/com/fr/design/gui/date/UICalendarPanel.java b/designer-base/src/main/java/com/fr/design/gui/date/UICalendarPanel.java index 7a9181e560..99356b7ad2 100644 --- a/designer-base/src/main/java/com/fr/design/gui/date/UICalendarPanel.java +++ b/designer-base/src/main/java/com/fr/design/gui/date/UICalendarPanel.java @@ -5,29 +5,22 @@ import com.fine.theme.icon.LazyIcon; import com.fine.theme.light.ui.FineRoundBorder; import com.fine.theme.utils.FineUIStyle; import com.fine.theme.utils.FineUIUtils; -import com.formdev.flatlaf.ui.FlatUIUtils; import com.formdev.flatlaf.util.ScaledEmptyBorder; import com.fr.design.border.FineBorderFactory; import com.fr.design.carton.MonthlyCartonFile; import com.fr.design.carton.SwitchForSwingChecker; -import com.fr.design.constants.UIConstants; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ilable.UILabel; -import com.fr.design.gui.itextfield.UITextField; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.utils.DesignUtils; import com.fr.general.GeneralUtils; -import com.fr.stable.Constants; import com.fr.stable.StableUtils; import com.fr.stable.StringUtils; import javax.swing.Box; import javax.swing.Icon; -import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingConstants; -import javax.swing.UIManager; -import javax.swing.border.LineBorder; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.EventListenerList; @@ -60,9 +53,10 @@ import static com.fine.theme.utils.FineUIStyle.STYLE_TEXT; import static com.fine.theme.utils.FineUIStyle.setStyle; public class UICalendarPanel extends JPanel { + private static final String UI_CLASS_ID = "CalendarPaneUI"; - private static final Font FONT_UI = DesignUtils.getDefaultGUIFont().applySize(scale(12)); - private static final Font FONT_BLACK = new Font(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Black_Font"), Font.PLAIN, scale(12)); +// private static final Font FONT_UI = DesignUtils.getDefaultGUIFont().applySize(scale(12)); +// private static final Font FONT_BLACK = new Font(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Black_Font"), Font.PLAIN, scale(12)); private static final int WEEKDAY_COUNT = 7; private static final int TOTAL_DAYS_COUNT = 42; protected final Insets defaultInsets = new Insets(0, 6, 0, 6); @@ -124,10 +118,6 @@ public class UICalendarPanel extends JPanel { calendar = Calendar.getInstance(); dayBttListener = createDayBttListener(); - //renderer this - setBackground(FlatUIUtils.getUIColor("fill.normal", Color.WHITE)); - setBorder(new LineBorder(FlatUIUtils.getUIColor("defaultBorderColor", Color.BLACK))); - setLayout(FRGUIPaneFactory.createBorderLayout()); add(BorderLayout.NORTH, createNorthPane()); add(BorderLayout.CENTER, createCenterPane()); @@ -153,7 +143,6 @@ public class UICalendarPanel extends JPanel { UIButton monthMinus = createSkipButton(Calendar.MONTH, -1, new LazyIcon("left_arrow")); pNorth.add(monthMinus); monthLabel = new UILabel("", UILabel.CENTER); - monthLabel.setFont(FONT_UI); pNorth.add(Box.createHorizontalGlue()); pNorth.add(monthLabel); pNorth.add(Box.createHorizontalGlue()); @@ -180,7 +169,6 @@ public class UICalendarPanel extends JPanel { for (int i = 1; i <= WEEKDAY_COUNT; i++) { UILabel label = new UILabel(); label.setHorizontalAlignment(UILabel.CENTER); - label.setFont(FONT_BLACK); label.setText(strWeeks[i]); label.setPreferredSize(createScaleDimension(WEEK_LABEL_WIDTH, WEEK_LABEL_HEIGHT)); pWeeks.add(label); @@ -211,7 +199,6 @@ public class UICalendarPanel extends JPanel { sPane.setOpaque(false); sPane.setLayout(new BorderLayout()); UILabel timeLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Time") + ":"); - timeLabel.setFont(FONT_UI); hms = new HMSPane(); UIButton okButton = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_OK")) { @@ -223,7 +210,6 @@ public class UICalendarPanel extends JPanel { return new Insets(0, 0, 0, 0); } }; - okButton.setFont(FONT_UI); okButton.setVerticalAlignment(SwingConstants.CENTER); okButton.addActionListener(new ActionListener() { @@ -313,9 +299,6 @@ public class UICalendarPanel extends JPanel { } else { label.addMouseListener(dayBttListener); } - if (!isCurrentMonth) { - FineUIStyle.setStyle(label, FineUIStyle.GRAY_BUTTON); - } } /** * 更新日期 @@ -366,11 +349,12 @@ public class UICalendarPanel extends JPanel { isCurrentMonth = !isCurrentMonth; } setUIDayLabel(label, isCurrentMonth, setupCalendar, logSet); + label.setCurrentMonth(isCurrentMonth); days.add(label); //当前选择的日期 if (setupCalendar.get(Calendar.DAY_OF_MONTH) == selectedCalendar.get(Calendar.DAY_OF_MONTH) && isCurrentMonth) { - label.getModel().setSelected(true); days.setSelectedIndex(i); + label.setSelected(true); this.selectedDate = label.getDate(); this.calendar.setTime(this.selectedDate); } @@ -409,6 +393,10 @@ public class UICalendarPanel extends JPanel { if (isEnabled()) { UIDayLabel com = (UIDayLabel) e.getComponent(); days.setSelectedIndex(com.getIndex()); + com.setHovered(false); + com.setPressed(true); + com.getParent().validate(); + com.getParent().repaint(); } } @@ -427,18 +415,25 @@ public class UICalendarPanel extends JPanel { public void mouseEntered(MouseEvent e) { if (isEnabled()) { UIDayLabel com = (UIDayLabel) e.getComponent(); + com.setHovered(true); if (com.getIndex() == days.selectedIndex) { return; } days.setFloatIndex(com.getIndex()); + com.getParent().validate(); + com.getParent().repaint(); } } public void mouseExited(MouseEvent e) { if (isEnabled()) { + UIDayLabel com = (UIDayLabel) e.getComponent(); + com.setHovered(false); + com.setPressed(false); days.setFloatIndex(-1); - days.repaint(); + com.getParent().validate(); + com.getParent().repaint(); } } }; @@ -648,21 +643,8 @@ public class UICalendarPanel extends JPanel { } } - public static void main(String[] args) { - JFrame frame = new JFrame(); - UICalendarPanel calendarPanel = new UICalendarPanel(); - final UITextField field = new UITextField(); - field.setPreferredSize(new Dimension(120, 25)); - calendarPanel.addDateChangeListener(new ChangeListener() { - public void stateChanged(ChangeEvent e) { - Date selectedDate = (Date) e.getSource(); - SimpleDateFormat f = new SimpleDateFormat("yyyy/MM/dd"); - field.setText(f.format(selectedDate)); - } - }); - frame.getContentPane().setLayout(FRGUIPaneFactory.createCenterFlowLayout()); - frame.getContentPane().add(field); - frame.getContentPane().add(calendarPanel); - frame.setVisible(true); + @Override + public String getUIClassID() { + return UI_CLASS_ID; } } diff --git a/designer-base/src/main/java/com/fr/design/gui/date/UIDayLabel.java b/designer-base/src/main/java/com/fr/design/gui/date/UIDayLabel.java index bcf29f6e01..819bb1c270 100644 --- a/designer-base/src/main/java/com/fr/design/gui/date/UIDayLabel.java +++ b/designer-base/src/main/java/com/fr/design/gui/date/UIDayLabel.java @@ -1,14 +1,10 @@ package com.fr.design.gui.date; -import com.fine.theme.utils.FineUIStyle; -import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ilable.UILabel; import com.fr.design.utils.DesignUtils; -import java.awt.Insets; import java.text.SimpleDateFormat; import java.util.Date; - import static com.fine.theme.utils.FineUIScale.scale; @@ -18,11 +14,35 @@ import static com.fine.theme.utils.FineUIScale.scale; * @since 12.0 * Created on 2024/09/22 */ -public class UIDayLabel extends UIButton { - private static final String UI_CLASS_ID = "DayLabelUI"; +public class UIDayLabel extends UILabel { private Date date = null; private int index; + private boolean pressed = false; + private boolean hovered = false; + private boolean selected = false; + private boolean currentMonth = false; + private boolean smallLabel = false; + + public boolean isHovered() { + return hovered; + } + + public boolean isPressed() { + return pressed; + } + + public boolean isSelected() { + return selected; + } + + public boolean isCurrentMonth() { + return currentMonth; + } + + public boolean isSmallLabel() { + return smallLabel; + } /** * 日期格式(TODAY/TIP用) @@ -38,12 +58,11 @@ public class UIDayLabel extends UIButton { } public UIDayLabel(Date date, boolean isSmallLabel) { - FineUIStyle.setStyle(this, FineUIStyle.ORIGINAL_BUTTON); + setOpaque(false); setHorizontalAlignment(UILabel.CENTER); - setFont(DesignUtils.getDefaultGUIFont().applySize(scale(12))); - setMargin(new Insets(0, 0, 0, 0)); this.date = date; - if (isSmallLabel) { + this.smallLabel = isSmallLabel; + if (smallLabel) { setText(dayFormat.format(date)); } else { setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Today") + ":" + dateFormat.format(new Date())); @@ -55,6 +74,23 @@ public class UIDayLabel extends UIButton { return date; } + public void setHovered(boolean hovered) { + this.hovered = hovered; + } + + public void setPressed(boolean pressed) { + this.pressed = pressed; + } + + public void setSelected(boolean selected) { + this.selected = selected; + } + + public void setCurrentMonth(boolean currentMonth) { + this.currentMonth = currentMonth; + } + + public void setDate(Date date) { this.date = date; } @@ -67,9 +103,4 @@ public class UIDayLabel extends UIButton { return this.index; } - @Override - public String getUIClassID() { - return UI_CLASS_ID; - } - } \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fine/theme/light/ui/laf/FineLaf.properties b/designer-base/src/main/resources/com/fine/theme/light/ui/laf/FineLaf.properties index d2d7133f02..86799ed9f2 100644 --- a/designer-base/src/main/resources/com/fine/theme/light/ui/laf/FineLaf.properties +++ b/designer-base/src/main/resources/com/fine/theme/light/ui/laf/FineLaf.properties @@ -7,7 +7,7 @@ ColorChooserUI=com.formdev.flatlaf.ui.FlatColorChooserUI ComboBoxUI=com.fine.theme.light.ui.FineComboBoxUI DesktopIconUI=com.formdev.flatlaf.ui.FlatDesktopIconUI DesktopPaneUI=com.formdev.flatlaf.ui.FlatDesktopPaneUI -DayLabelUI=com.fine.theme.light.ui.FineDayLabelUI +CalendarPaneUI=com.fine.theme.light.ui.FineCalendarPaneUI EditorPaneUI=com.formdev.flatlaf.ui.FlatEditorPaneUI FileChooserUI=com.formdev.flatlaf.ui.FlatFileChooserUI FormattedTextFieldUI=com.formdev.flatlaf.ui.FlatFormattedTextFieldUI diff --git a/designer-base/src/main/resources/com/fine/theme/light/ui/laf/FineLightLaf.properties b/designer-base/src/main/resources/com/fine/theme/light/ui/laf/FineLightLaf.properties index 130ae78374..644c474ba0 100644 --- a/designer-base/src/main/resources/com/fine/theme/light/ui/laf/FineLightLaf.properties +++ b/designer-base/src/main/resources/com/fine/theme/light/ui/laf/FineLightLaf.properties @@ -411,7 +411,12 @@ Label.warningColor = #F1393C Label.secondaryColor = #0A1C38A8 # ---- Calendar ---- +Calendar.background = $fill.normal Calendar.day.selectedBackground = #2576EF +Calendar.day.hoverBackground = #E6E9EF +Calendar.day.pressedBackground = #DADEE7 +Calendar.dayOtherMonth.foreground = fade(@foreground, 29%) +Calendar.day.arc = 6 #---- HelpButton ---- diff --git a/designer-base/src/test/java/com/fr/design/gui/storybook/components/UICalendarPaneStoryBoard.java b/designer-base/src/test/java/com/fr/design/gui/storybook/components/UICalendarPaneStoryBoard.java new file mode 100644 index 0000000000..072b8e2eec --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/gui/storybook/components/UICalendarPaneStoryBoard.java @@ -0,0 +1,32 @@ +package com.fr.design.gui.storybook.components; + +import com.fine.theme.light.ui.FineRoundBorder; +import com.fr.design.gui.date.UICalendarPanel; +import com.fr.design.gui.date.UIDatePicker; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.storybook.StoryBoard; + +import javax.swing.*; +import java.awt.*; +import java.util.Date; + +import static com.fine.swing.ui.layout.Layouts.*; + +public class UICalendarPaneStoryBoard extends StoryBoard { + public UICalendarPaneStoryBoard() { + super("日期控件"); + UICalendarPanel calendarPanel = new UICalendarPanel(true); + calendarPanel.setSelectedDate(new Date()); + add( + cell(new UILabel("日期下拉框")).with(this::h3), + row(cell(new UIDatePicker(2)).with(this::setFixSize), flex()), + cell(new UILabel("日期")).with(this::h3), + row(cell(calendarPanel), flex()) + ); + } + + private void setFixSize(JComponent component) { + component.setPreferredSize(new Dimension(240, component.getHeight())); + component.setBorder(new FineRoundBorder()); + } +}