diff --git a/app/src/main/java/muon/App.java b/app/src/main/java/muon/App.java index aa7209a7..7c68f47f 100644 --- a/app/src/main/java/muon/App.java +++ b/app/src/main/java/muon/App.java @@ -1,17 +1,18 @@ package muon; +import muon.ui.styles.AppTheme; import muon.ui.styles.FlatLookAndFeel; import muon.ui.widgets.HomePanel; -import muon.ui.widgets.TabItem; +import muon.ui.widgets.SessionManagerDialog; import muon.ui.widgets.TabbedPanel; -import muon.util.FontIcon; +import muon.util.AppUtils; +import muon.util.IconCode; import muon.util.IconFont; import javax.swing.*; import javax.swing.border.CompoundBorder; import javax.swing.border.EmptyBorder; import javax.swing.border.MatteBorder; -import javax.swing.plaf.metal.MetalLookAndFeel; import javax.swing.table.TableCellRenderer; import java.awt.*; import java.awt.event.MouseAdapter; @@ -38,12 +39,18 @@ public static void main(String[] args) throws InterruptedException, InvocationTa //JFrame.setDefaultLookAndFeelDecorated(false); JFrame f = new JFrame(); //f.setUndecorated(true); - f.setSize(800, 600); + f.setSize(AppUtils.calculateDefaultWindowSize()); f.setLocationRelativeTo(null); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - f.getContentPane().setBackground(Color.BLACK); - f.setBackground(Color.BLACK); - f.add(new HomePanel()); + f.getContentPane().setBackground(AppTheme.INSTANCE.getBackground()); + f.setBackground(AppTheme.INSTANCE.getBackground()); + final var hp = new HomePanel(null, e -> { + new SessionManagerDialog(f).setVisible(true); + f.getContentPane().removeAll(); + f.getContentPane().add(createMainPanel()); + f.getContentPane().validate(); + }); + f.add(hp); //var toolbar = createToolbar(); //f.add(toolbar, BorderLayout.NORTH); //f.add(createMainPanel()); @@ -72,6 +79,7 @@ private static JPanel createFileBrowser(EmptyBorder border, boolean right) { addressBar.add(addressIcon, BorderLayout.WEST); var txtAddress = new JTextField(); + txtAddress.putClientProperty("textField.noBorder",Boolean.TRUE); txtAddress.setBackground(c1); txtAddress.setForeground(new Color(100, 100, 100)); txtAddress.setBorder(new EmptyBorder(0, 0, 0, 0)); @@ -294,7 +302,7 @@ private static JPanel createBottomPanel() { return panel; } - private static JPanel createContentPanel(){ + private static JPanel createContentPanel() { var mainTop = new JPanel(new GridLayout(1, 2)); mainTop.add(createFileBrowser(new MatteBorder(0, 0, 0, 1, new Color(15, 15, 15)), false)); mainTop.add(createFileBrowser(border, true)); @@ -318,12 +326,11 @@ private static JPanel createMainPanel() { new Color(31, 31, 31), new Color(130, 130, 130), new Color(180, 180, 180), - FontIcon.RI_INSTANCE_LINE, - FontIcon.RI_CLOSE_LINE, + IconCode.RI_CLOSE_LINE, Color.BLACK ); - tabbedPanel.addTab("tab1", FontIcon.RI_INSTANCE_LINE, createContentPanel()); - tabbedPanel.addTab("tab2", FontIcon.RI_INSTANCE_LINE, createContentPanel()); + tabbedPanel.addTab("tab1", IconCode.RI_INSTANCE_LINE, createContentPanel()); + tabbedPanel.addTab("tab2", IconCode.RI_INSTANCE_LINE, createContentPanel()); // // // diff --git a/app/src/main/java/muon/model/ISessionListItem.java b/app/src/main/java/muon/model/ISessionListItem.java new file mode 100644 index 00000000..8d151bcd --- /dev/null +++ b/app/src/main/java/muon/model/ISessionListItem.java @@ -0,0 +1,6 @@ +package muon.model; + +public interface ISessionListItem { + String getName(); + String getUser(); +} diff --git a/app/src/main/java/muon/ui/styles/AppTheme.java b/app/src/main/java/muon/ui/styles/AppTheme.java index f451bfa3..07d34cba 100644 --- a/app/src/main/java/muon/ui/styles/AppTheme.java +++ b/app/src/main/java/muon/ui/styles/AppTheme.java @@ -1,15 +1,132 @@ package muon.ui.styles; +import javax.swing.border.EmptyBorder; +import javax.swing.border.LineBorder; import java.awt.*; public class AppTheme { - public static final AppTheme INSTANCE=new AppTheme(); + public static final AppTheme INSTANCE = new AppTheme(); + public static Insets BUTTON_MARGIN = new Insets(150, 15, 5, 15); - public Color getBackground(){ + public Color getBackground() { return new Color(31, 31, 31); } - public Color getTabSelectionColor(){ + public Color getButtonBackground() { + return new Color(35, 35, 35); + } + + public Color getButtonRollOverBackground() { + return new Color(40, 40, 40); + } + + public Color getButtonPressedBackground() { + return new Color(27, 27, 27); + } + + public Color getDarkControlBackground() { + return new Color(24, 24, 24); + } + + public Color getForeground() { + return new Color(120, 120, 120); + } + + public Color getLightForeground() { + return new Color(100, 100, 100); + } + + public Color getHomePanelButtonColor() { + return new Color(31, 31, 31); + } + + public Color getButtonBorderColor() { + return new Color(54, 54, 54); + } + + public Color getTextFieldBorderColor() { + return new Color(64, 64, 64); + } + + public Color getSelectionColor() { return new Color(52, 117, 233); } + + public Color getSelectionForeground() { + return Color.WHITE; + } + + public int getButtonBorderArc() { + return 7; + } + + public Color getSplitPaneBackground() { + return Color.BLACK; + } + + public Color getListSelectionColor(){ + return new Color(46,67,110); + } + + public Object[] getDefaultStyles() { + Font widgetFont = new Font(Font.DIALOG, Font.PLAIN, 12); + return new Object[]{ + "Button.font", widgetFont, + "Button.background", getButtonBackground(), + "Button.foreground", getForeground(), + "Button.light", getButtonRollOverBackground(), + "Button.highlight", getButtonPressedBackground(), + "Button.border", new EmptyBorder(new Insets(5, 15, 5, 15)), + + "Label.font", widgetFont, + "Label.background", getBackground(), + "Label.foreground", getForeground(), + "Label.disabledForeground", getForeground(), + "Label.disabledShadow", getForeground(), + "Label.border", null, + + "TextField.background", getBackground(), + "TextField.border", new EmptyBorder(5, 5, 5, 5), + "TextField.foreground", getForeground(), + "TextField.selectionBackground", getSelectionColor(), + "TextField.selectionForeground", getSelectionForeground(), + "TextField.caretForeground", getForeground(), + + "PasswordField.background", getBackground(), + "PasswordField.border", new LineBorder(Color.RED, 5), + "PasswordField.foreground", getForeground(), + "PasswordField.selectionBackground", getSelectionColor(), + "PasswordField.selectionForeground", getSelectionForeground(), + "PasswordField.caretForeground", getForeground(), + + "Tree.background", getBackground(), + "Tree.foreground", getForeground(), +// "Tree.openIcon", new FontIcon(FontIconCodes.RI_FOLDER_OPEN_FILL, +// 24, 24, 16.0f, getForeground()), +// "Tree.closedIcon", new FontIcon(FontIconCodes.RI_FOLDER_FILL, +// 24, 24, 16.0f, getForeground()), +// "Tree.leafIcon", new FontIcon(FontIconCodes.RI_CLOSE_LINE, +// 24, 24, 16.0f, getForeground()), + "Tree.selectionForeground", getSelectionForeground(), + "Tree.textForeground", getForeground(), + "Tree.selectionBackground", getListSelectionColor(), + "Tree.textBackground", getBackground(), + "Tree.rendererFillBackground", true, + //"Tree.rendererMargins", new Insets(25,25,5,5), + "Tree.selectionBorderColor", getListSelectionColor(), + + "SplitPane.background", Color.BLACK, + "SplitPane.border", new EmptyBorder(0, 0, 0, 0), + "SplitPaneDivider.border", new EmptyBorder(0, 0, 0, 0), + + "ComboBox.background", getBackground(), + "ComboBox.foreground", getForeground(), + "ComboBox.border", new EmptyBorder(0, 0, 0, 0), + "ComboBox.padding", new Insets(5, 5, 5, 5), + "ComboBox.squareButton", Boolean.FALSE, + "ComboBox.Border", new EmptyBorder(3,3,3,3), + + "Panel.background", getBackground(), + }; + } } diff --git a/app/src/main/java/muon/ui/styles/FlatButtonUI.java b/app/src/main/java/muon/ui/styles/FlatButtonUI.java index e8da1a47..dbfb25ec 100644 --- a/app/src/main/java/muon/ui/styles/FlatButtonUI.java +++ b/app/src/main/java/muon/ui/styles/FlatButtonUI.java @@ -4,60 +4,59 @@ import javax.swing.plaf.*; import javax.swing.plaf.basic.*; import java.awt.*; +import java.awt.geom.RoundRectangle2D; public class FlatButtonUI extends BasicButtonUI { - static FlatButtonUI buttonUI; public static ComponentUI createUI(JComponent c) { - if (buttonUI == null) { - buttonUI = new FlatButtonUI(); - } - return buttonUI; + return new FlatButtonUI(); } @Override public void installUI(JComponent c) { super.installUI(c); - if (c instanceof JButton) { - JButton btn = (JButton) c; + if (c instanceof JButton btn) { + btn.setRolloverEnabled(true); + if (btn.getBackground() == null) { + btn.setBackground(AppTheme.INSTANCE.getButtonBackground()); + } + if (btn.getClientProperty("button.arc") == null) { + btn.putClientProperty("button.arc", AppTheme.INSTANCE.getButtonBorderArc()); + } + btn.setOpaque(false); } } protected void paintButtonNormal(Graphics g, AbstractButton b) { - if (!b.isOpaque()) { + if (b.isContentAreaFilled()) { Graphics2D g2 = (Graphics2D) g; - g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); - g2.setPaint(b.getBackground()); - g2.fillRect(0, 0, b.getWidth(), b.getHeight()); + g2.setColor(b.getBackground()); + Integer arc = (Integer) b.getClientProperty("button.arc"); + g2.fillRoundRect(0, 0, b.getWidth(), b.getHeight(), arc, arc); + + if (b.isBorderPainted()) { + g2.setColor(AppTheme.INSTANCE.getButtonBorderColor()); + g2.drawRoundRect(0, 0, b.getWidth() - 1, b.getHeight() - 1, arc, arc); + } } } protected void paintButtonPressed(Graphics g, AbstractButton b) { - Graphics2D g2 = (Graphics2D) g; - g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); - g2.setColor(b.getBackground()); - // Color color = (Color) b.getClientProperty("xdmbutton.pressedcolor"); - // if (color != null) { - // g2.setPaint(color); - // } else { - // g2.setPaint(Color.GRAY); - // } - g2.fillRect(0, 0, b.getWidth(), b.getHeight()); + if (!Boolean.TRUE.equals(b.getClientProperty("button.noPressed"))) { + Graphics2D g2 = (Graphics2D) g; + g2.setColor(AppTheme.INSTANCE.getButtonPressedBackground()); + Integer arc = (Integer) b.getClientProperty("button.arc"); + g2.fillRoundRect(0, 0, b.getWidth(), b.getHeight(), arc, arc); + } } protected void paintButtonRollOver(Graphics g, AbstractButton b) { - Graphics2D g2 = (Graphics2D) g; - g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); - // if (b.getClientProperty("xdmbutton.grayrollover") != null) { - // g2.setPaint(Color.DARK_GRAY); - // } else { - // g2.setPaint(ColorResource.getSelectionColor()); - // } - g2.setColor(b.getBackground()); - g2.fillRect(0, 0, b.getWidth(), b.getHeight()); + if (b.isRolloverEnabled()) { + Graphics2D g2 = (Graphics2D) g; + g2.setColor(AppTheme.INSTANCE.getButtonRollOverBackground()); + Integer arc = (Integer) b.getClientProperty("button.arc"); + g2.fillRoundRect(0, 0, b.getWidth(), b.getHeight(), arc, arc); + } } public void paint(Graphics g, JComponent c) { @@ -65,6 +64,7 @@ public void paint(Graphics g, JComponent c) { Graphics2D g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB); AbstractButton b = (AbstractButton) c; ButtonModel bm = b.getModel(); diff --git a/app/src/main/java/muon/ui/styles/FlatComboBoxUI.java b/app/src/main/java/muon/ui/styles/FlatComboBoxUI.java new file mode 100644 index 00000000..2edf692c --- /dev/null +++ b/app/src/main/java/muon/ui/styles/FlatComboBoxUI.java @@ -0,0 +1,78 @@ +package muon.ui.styles; + +import muon.util.IconCode; +import muon.util.IconFont; + +import javax.swing.*; +import javax.swing.border.EmptyBorder; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicComboBoxUI; +import java.awt.*; + +public class FlatComboBoxUI extends BasicComboBoxUI { + public static ComponentUI createUI(JComponent x) { + return new FlatComboBoxUI(); + } + + @Override + public void paint(Graphics g, JComponent c) { + + Graphics2D g2 = (Graphics2D) g; + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB); + + super.paint(g2, c); + + + g.setColor(c.isFocusOwner() ? AppTheme.INSTANCE.getSelectionColor() : + AppTheme.INSTANCE.getTextFieldBorderColor()); + g.drawRoundRect(0, 0, c.getWidth() - 1, c.getHeight() - 1, + AppTheme.INSTANCE.getButtonBorderArc(), AppTheme.INSTANCE.getButtonBorderArc()); + + } + + @Override + public void paintCurrentValue(Graphics g, Rectangle bounds, boolean hasFocus) { + //super.paintCurrentValue(g, bounds, hasFocus); + ListCellRenderer renderer = comboBox.getRenderer(); + Component c = renderer.getListCellRendererComponent(listBox, + comboBox.getSelectedItem(), + -1, + false, + false); + c.setBackground(UIManager.getColor("ComboBox.background")); + c.setFont(comboBox.getFont()); + c.setForeground(comboBox.getForeground()); + c.setBackground(comboBox.getBackground()); + boolean shouldValidate = false; + if (c instanceof JPanel) { + shouldValidate = true; + } + int x = bounds.x, y = bounds.y, w = bounds.width, h = bounds.height; + if (padding != null) { + x = bounds.x + padding.left; + y = bounds.y + padding.top; + w = bounds.width - (padding.left + padding.right); + h = bounds.height - (padding.top + padding.bottom); + } + + currentValuePane.paintComponent(g, c, comboBox, x, y, w, h, shouldValidate); + } + + @Override + protected JButton createArrowButton() { + var button = new JButton(); + button.setContentAreaFilled(false); + button.setRolloverEnabled(false); + button.setOpaque(false); + button.setMargin(new Insets(0, 0, 0, 0)); + button.setFont(IconFont.getSharedInstance().getIconFont(16)); + button.setText(IconCode.RI_ARROW_DOWN_S_LINE.getValue()); + button.setForeground(AppTheme.INSTANCE.getForeground()); + button.setName("ComboBox.arrowButton"); + button.setBorder(new EmptyBorder(0, 5, 0, 5)); + button.putClientProperty("button.noPressed", Boolean.TRUE); + return button; + } +} diff --git a/app/src/main/java/muon/ui/styles/FlatLabelUI.java b/app/src/main/java/muon/ui/styles/FlatLabelUI.java new file mode 100644 index 00000000..a74b960a --- /dev/null +++ b/app/src/main/java/muon/ui/styles/FlatLabelUI.java @@ -0,0 +1,32 @@ +package muon.ui.styles; + +import javax.swing.*; +import javax.swing.plaf.*; +import javax.swing.plaf.basic.*; +import java.awt.*; + +public class FlatLabelUI extends BasicLabelUI { + private static LabelUI labelUI; + + public static ComponentUI createUI(JComponent c) { + if (labelUI == null) { + labelUI = new FlatLabelUI(); + } + return labelUI; + } + + @Override + public void installUI(JComponent c) { + super.installUI(c); + } + + @Override + public void paint(Graphics g, JComponent c) { + Graphics2D g2 = (Graphics2D) g; + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB); + + super.paint(g2, c); + } +} diff --git a/app/src/main/java/muon/ui/styles/FlatLookAndFeel.java b/app/src/main/java/muon/ui/styles/FlatLookAndFeel.java index b576e4aa..76cccc43 100644 --- a/app/src/main/java/muon/ui/styles/FlatLookAndFeel.java +++ b/app/src/main/java/muon/ui/styles/FlatLookAndFeel.java @@ -1,8 +1,31 @@ package muon.ui.styles; -import javax.swing.plaf.basic.BasicLookAndFeel; +import javax.swing.*; +import javax.swing.plaf.basic.*; +import java.awt.*; public class FlatLookAndFeel extends BasicLookAndFeel { + + @Override + public void initClassDefaults(UIDefaults table) { + super.initClassDefaults(table); + table.putDefaults(new Object[]{ + "ButtonUI", FlatButtonUI.class.getName(), + "TextFieldUI", FlatTextFieldUI.class.getName(), + "PasswordFieldUI", FlatPasswordFieldUI.class.getName(), + "TreeUI", FlatTreeUI.class.getName(), + "SplitPaneUI", FlatSplitPaneUI.class.getName(), + "PanelUI", FlatPanelUI.class.getName(), + "ComboBoxUI", FlatComboBoxUI.class.getName(), + "LabelUI", FlatLabelUI.class.getName() + }); + } + + protected void initComponentDefaults(UIDefaults table) { + super.initComponentDefaults(table); + table.putDefaults(AppTheme.INSTANCE.getDefaultStyles()); + } + @Override public String getName() { return "FlatLookAndFeel"; diff --git a/app/src/main/java/muon/ui/styles/FlatPanelUI.java b/app/src/main/java/muon/ui/styles/FlatPanelUI.java new file mode 100644 index 00000000..b0c67640 --- /dev/null +++ b/app/src/main/java/muon/ui/styles/FlatPanelUI.java @@ -0,0 +1,21 @@ +package muon.ui.styles; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicPanelUI; +import java.awt.*; + +public class FlatPanelUI extends BasicPanelUI { + public static ComponentUI createUI(JComponent x) { + return new FlatPanelUI(); + } + + @Override + public void paint(Graphics g, JComponent c) { + Graphics2D g2 = (Graphics2D) g; + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB); + super.paint(g2, c); + } +} diff --git a/app/src/main/java/muon/ui/styles/FlatPasswordFieldUI.java b/app/src/main/java/muon/ui/styles/FlatPasswordFieldUI.java new file mode 100644 index 00000000..572d597a --- /dev/null +++ b/app/src/main/java/muon/ui/styles/FlatPasswordFieldUI.java @@ -0,0 +1,55 @@ +package muon.ui.styles; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicTextFieldUI; +import javax.swing.text.JTextComponent; +import java.awt.*; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; + +public class FlatPasswordFieldUI extends BasicTextFieldUI implements FocusListener { + private JTextComponent editor; + + public static ComponentUI createUI(JComponent c) { + return new FlatPasswordFieldUI(); + } + + public void installUI(JComponent c) { + super.installUI(c); + if (c instanceof JTextComponent) { + editor = (JTextComponent) c; + editor.putClientProperty("textField.arc", AppTheme.INSTANCE.getButtonBorderArc()); + editor.addFocusListener(this); + } + } + + @Override + protected void paintSafely(Graphics g) { + Graphics2D g2 = (Graphics2D) g; + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB); + super.paintSafely(g2); + } + + @Override + protected void paintBackground(Graphics g) { + Integer arc = (Integer) editor.getClientProperty("textField.arc"); + g.setColor(editor.getBackground()); + g.fillRoundRect(0, 0, editor.getWidth(), editor.getHeight(), arc, arc); + + g.setColor(editor.isFocusOwner() ? AppTheme.INSTANCE.getSelectionColor() : AppTheme.INSTANCE.getButtonBorderColor()); + g.drawRoundRect(0, 0, editor.getWidth() - 1, editor.getHeight() - 1, arc, arc); + } + + @Override + public void focusGained(FocusEvent e) { + editor.repaint(); + } + + @Override + public void focusLost(FocusEvent e) { + editor.repaint(); + } +} diff --git a/app/src/main/java/muon/ui/styles/FlatSplitPaneUI.java b/app/src/main/java/muon/ui/styles/FlatSplitPaneUI.java new file mode 100644 index 00000000..4ecbabeb --- /dev/null +++ b/app/src/main/java/muon/ui/styles/FlatSplitPaneUI.java @@ -0,0 +1,34 @@ +package muon.ui.styles; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicSplitPaneDivider; +import javax.swing.plaf.basic.BasicSplitPaneUI; +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +public class FlatSplitPaneUI extends BasicSplitPaneUI { + public static ComponentUI createUI(JComponent x) { + return new FlatSplitPaneUI(); + } + + @Override + public BasicSplitPaneDivider createDefaultDivider() { + var divider = super.createDefaultDivider(); + divider.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + splitPane.setBackground(AppTheme.INSTANCE.getSelectionColor()); + splitPane.setDividerSize(5); + } + + @Override + public void mouseExited(MouseEvent e) { + splitPane.setBackground(AppTheme.INSTANCE.getSplitPaneBackground()); + splitPane.setDividerSize(1); + } + }); + return divider; + } +} diff --git a/app/src/main/java/muon/ui/styles/FlatTextFieldUI.java b/app/src/main/java/muon/ui/styles/FlatTextFieldUI.java new file mode 100644 index 00000000..59e19088 --- /dev/null +++ b/app/src/main/java/muon/ui/styles/FlatTextFieldUI.java @@ -0,0 +1,60 @@ +package muon.ui.styles; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicTextFieldUI; +import javax.swing.text.JTextComponent; +import java.awt.*; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.util.Objects; + +public class FlatTextFieldUI extends BasicTextFieldUI implements FocusListener { + private JTextComponent editor; + + public static ComponentUI createUI(JComponent c) { + return new FlatTextFieldUI(); + } + + public void installUI(JComponent c) { + super.installUI(c); + if (c instanceof JTextComponent) { + editor = (JTextComponent) c; + editor.putClientProperty("textField.arc", AppTheme.INSTANCE.getButtonBorderArc()); + editor.addFocusListener(this); + } + } + + @Override + protected void paintSafely(Graphics g) { + Graphics2D g2 = (Graphics2D) g; + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB); + super.paintSafely(g2); + } + + @Override + protected void paintBackground(Graphics g) { + Integer arc = (Integer) editor.getClientProperty("textField.arc"); + g.setColor(editor.getBackground()); + g.fillRoundRect(0, 0, editor.getWidth(), editor.getHeight(), arc, arc); + + g.setColor(editor.isFocusOwner() ? AppTheme.INSTANCE.getSelectionColor() : + AppTheme.INSTANCE.getTextFieldBorderColor()); + if (Boolean.TRUE.equals(editor.getClientProperty("textField.noBorder"))) { + return; + } + g.drawRoundRect(0, 0, editor.getWidth() - 1, editor.getHeight() - 1, arc, arc); + } + + @Override + public void focusGained(FocusEvent e) { + editor.repaint(); + } + + @Override + public void focusLost(FocusEvent e) { + editor.repaint(); + } +} diff --git a/app/src/main/java/muon/ui/styles/FlatTreeRenderer.java b/app/src/main/java/muon/ui/styles/FlatTreeRenderer.java new file mode 100644 index 00000000..facc8903 --- /dev/null +++ b/app/src/main/java/muon/ui/styles/FlatTreeRenderer.java @@ -0,0 +1,99 @@ +package muon.ui.styles; + +import muon.util.IconCode; +import muon.util.IconFont; + +import javax.swing.*; +import javax.swing.border.EmptyBorder; +import javax.swing.tree.TreeCellRenderer; +import java.awt.*; + +public class FlatTreeRenderer implements TreeCellRenderer { + private JPanel panel; + private JLabel expandArrow, collapsedArrow, nodeIcon, leafIcon, text; + private Component blank; + + public FlatTreeRenderer() { + panel = new JPanel(null); + panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); + expandArrow = createLabel(IconCode.RI_ARROW_DOWN_S_LINE); + collapsedArrow = createLabel(IconCode.RI_ARROW_RIGHT_S_LINE); + nodeIcon = createLabel(IconCode.RI_FOLDER_LINE); + leafIcon = createLabel(IconCode.RI_INSTANCE_LINE); + + expandArrow.setBorder(new EmptyBorder(0,5,0,0)); + collapsedArrow.setBorder(new EmptyBorder(0,5,0,0)); + + int mw = 0, mh = 0; + for (var label : + new JLabel[]{expandArrow, collapsedArrow, nodeIcon, leafIcon}) { + var dim = label.getPreferredSize(); + if (dim.width > mw) { + mw = dim.width; + } + if (dim.height > mh) { + mh = dim.height; + } + } + + var dim = new Dimension(mw, mh); + for (var label : + new JLabel[]{expandArrow, collapsedArrow, nodeIcon, leafIcon}) { + label.setPreferredSize(dim); + label.setMinimumSize(dim); + label.setMaximumSize(dim); + } + + blank = Box.createRigidArea(dim); + text = new JLabel(); + + panel.add(blank); + panel.add(expandArrow); + panel.add(collapsedArrow); + panel.add(Box.createRigidArea(new Dimension(5,5))); + panel.add(nodeIcon); + panel.add(leafIcon); + panel.add(text); + panel.setBorder(new EmptyBorder(5, 5, 5, 5)); + +// var dim1=panel.getPreferredSize(); +// dim1.width=Short.MAX_VALUE; +// panel.setPreferredSize(dim1); + } + + public int getPreferredHeight() { + return panel.getPreferredSize().height; + } + + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { + text.setText(value.toString()); + if (leaf) { + expandArrow.setVisible(false); + collapsedArrow.setVisible(false); + nodeIcon.setVisible(false); + leafIcon.setVisible(true); + blank.setVisible(true); + } else { + expandArrow.setVisible(expanded); + collapsedArrow.setVisible(!expanded); + nodeIcon.setVisible(true); + leafIcon.setVisible(false); + blank.setVisible(false); + } + expandArrow.setForeground(selected ? AppTheme.INSTANCE.getSelectionForeground() : AppTheme.INSTANCE.getForeground()); + collapsedArrow.setForeground(selected ? AppTheme.INSTANCE.getSelectionForeground() : AppTheme.INSTANCE.getForeground()); + nodeIcon.setForeground(selected ? AppTheme.INSTANCE.getSelectionForeground() : AppTheme.INSTANCE.getForeground()); + leafIcon.setForeground(selected ? AppTheme.INSTANCE.getSelectionForeground() : AppTheme.INSTANCE.getForeground()); + text.setForeground(selected ? AppTheme.INSTANCE.getSelectionForeground() : AppTheme.INSTANCE.getForeground()); + panel.setBackground(selected ? AppTheme.INSTANCE.getListSelectionColor() : tree.getBackground()); + return panel; + } + + private JLabel createLabel(IconCode code) { + var lbl = new JLabel(); + lbl.setFont(IconFont.getSharedInstance().getIconFont(18.0f)); + lbl.setText(code.getValue()); + return lbl; + } +} diff --git a/app/src/main/java/muon/ui/styles/FlatTreeUI.java b/app/src/main/java/muon/ui/styles/FlatTreeUI.java new file mode 100644 index 00000000..b965616a --- /dev/null +++ b/app/src/main/java/muon/ui/styles/FlatTreeUI.java @@ -0,0 +1,74 @@ +package muon.ui.styles; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicTreeUI; +import javax.swing.tree.TreePath; +import java.awt.*; + +public class FlatTreeUI extends BasicTreeUI { + public static ComponentUI createUI(JComponent x) { + return new FlatTreeUI(); + } + + private JTree tree; + + @Override + public void installUI(JComponent c) { + super.installUI(c); + System.out.println(c); + if (c instanceof JTree) { + this.tree = (JTree) c; + } + } + + @Override + public void paint(Graphics g, JComponent c) { + Graphics2D g2 = (Graphics2D) g; + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB); + super.paint(g2, c); + } + + @Override + protected void paintRow(Graphics g, Rectangle clipBounds, Insets insets, Rectangle bounds, TreePath path, int row, boolean isExpanded, boolean hasBeenExpanded, boolean isLeaf) { + g.setColor(tree.isRowSelected(row) ? AppTheme.INSTANCE.getListSelectionColor() : tree.getBackground()); + g.fillRect(0, bounds.y, clipBounds.width , bounds.height); + bounds.x = bounds.x; + bounds.width = bounds.width; + super.paintRow(g, clipBounds, insets, bounds, path, row, isExpanded, hasBeenExpanded, isLeaf); + } + + @Override + protected void paintHorizontalLine(Graphics g, JComponent c, int y, int left, int right) { + //super.paintHorizontalLine(g, c, y, left, right); + } + + @Override + protected void paintVerticalLine(Graphics g, JComponent c, int x, int top, int bottom) { + //super.paintVerticalLine(g, c, x, top, bottom); + } + +// @Override +// public Icon getExpandedIcon() { +// return new FontIcon(FontIconCodes.RI_ARROW_DOWN_S_LINE, +// 24, 24, 18.0f, AppTheme.INSTANCE.getForeground()); +// } +// +// @Override +// public Icon getCollapsedIcon() { +// return new FontIcon(FontIconCodes.RI_ARROW_RIGHT_S_LINE, +// 24, 24, 18.0f, AppTheme.INSTANCE.getForeground()); +// } + + // @Override +// protected void paintVerticalPartOfLeg(Graphics g, Rectangle clipBounds, Insets insets, TreePath path) { +// //super.paintVerticalPartOfLeg(g, clipBounds, insets, path); +// } +// +// @Override +// protected void paintHorizontalPartOfLeg(Graphics g, Rectangle clipBounds, Insets insets, Rectangle bounds, TreePath path, int row, boolean isExpanded, boolean hasBeenExpanded, boolean isLeaf) { +// //super.paintHorizontalPartOfLeg(g, clipBounds, insets, bounds, path, row, isExpanded, hasBeenExpanded, isLeaf); +// } +} diff --git a/app/src/main/java/muon/ui/styles/FontIcon.java b/app/src/main/java/muon/ui/styles/FontIcon.java new file mode 100644 index 00000000..02c8cac5 --- /dev/null +++ b/app/src/main/java/muon/ui/styles/FontIcon.java @@ -0,0 +1,49 @@ +package muon.ui.styles; + +import muon.util.IconCode; +import muon.util.IconFont; + +import javax.swing.*; +import java.awt.*; + +public class FontIcon implements Icon { + + private int width, height; + private IconCode iconCode; + private Font font; + private Color color; + + public FontIcon(IconCode iconCode, int width, int height, float fontSize, Color color) { + this.iconCode = iconCode; + this.width = width; + this.height = height; + this.font = IconFont.getSharedInstance().getIconFont(fontSize); + this.color = color; + } + + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { + var color = g.getColor(); + var font = g.getFont(); + Graphics2D g2 = (Graphics2D) g; + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB); + g2.setColor(this.color); + g2.setFont(this.font); + g2.drawString(this.iconCode.getValue(), + x / 2 + width / 2, y + g.getFontMetrics().getAscent() + g.getFontMetrics().getDescent()); + g2.setFont(font); + g2.setColor(color); + } + + @Override + public int getIconWidth() { + return width; + } + + @Override + public int getIconHeight() { + return height; + } +} diff --git a/app/src/main/java/muon/ui/styles/RounderBorder.java b/app/src/main/java/muon/ui/styles/RounderBorder.java new file mode 100644 index 00000000..cbe058fe --- /dev/null +++ b/app/src/main/java/muon/ui/styles/RounderBorder.java @@ -0,0 +1,30 @@ +package muon.ui.styles; + +import javax.swing.border.Border; +import java.awt.*; + +public class RounderBorder implements Border { + private Insets insets; + private int arc; + private int thickness; + private Color color; + + public RounderBorder(Insets insets) { + this.insets = insets; + } + + @Override + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + + } + + @Override + public Insets getBorderInsets(Component c) { + return insets; + } + + @Override + public boolean isBorderOpaque() { + return false; + } +} diff --git a/app/src/main/java/muon/ui/widgets/HomePanel.java b/app/src/main/java/muon/ui/widgets/HomePanel.java index a87328b5..de19d586 100644 --- a/app/src/main/java/muon/ui/widgets/HomePanel.java +++ b/app/src/main/java/muon/ui/widgets/HomePanel.java @@ -1,26 +1,438 @@ package muon.ui.widgets; -import muon.ui.styles.AppTheme; -import muon.ui.styles.FlatButtonUI; +import muon.model.ISessionListItem; +import muon.ui.styles.*; +import muon.util.*; import javax.swing.*; -import javax.swing.plaf.basic.BasicButtonUI; +import javax.swing.border.EmptyBorder; import java.awt.*; +import java.awt.event.ActionListener; +import java.util.List; +import java.util.Objects; public class HomePanel extends JPanel { - public HomePanel() { + + public HomePanel(List sessions, + ActionListener onSessionManagerClicked) { super(null); - setBackground(AppTheme.INSTANCE.getBackground()); - setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); - var iconLabel = new JLabel("Jdadasdasd"); + setBackground(AppTheme.INSTANCE.getDarkControlBackground()); + setLayout(new GridBagLayout()); + + var constraint1 = new GridBagConstraints(); + constraint1.weightx = 0.3; + constraint1.weighty = 1; + constraint1.gridx = 0; + constraint1.fill = GridBagConstraints.BOTH; + constraint1.anchor = GridBagConstraints.CENTER; + + var constraint2 = new GridBagConstraints(); + constraint2.weightx = 0.7; + constraint2.weighty = 1; + constraint2.gridx = 1; + constraint2.fill = GridBagConstraints.BOTH; + + var leftPanel = createLeftPanel(onSessionManagerClicked); + var p1 = new JPanel(new GridBagLayout()); + p1.setBackground(AppTheme.INSTANCE.getDarkControlBackground()); + p1.add(leftPanel); + + var rightPanel = createRightPanel(sessions); + var p2 = new JPanel(new GridBagLayout()); + p2.setBackground(AppTheme.INSTANCE.getBackground()); + p2.add(rightPanel); + + add(p1, constraint1); + add(p2, constraint2); + +// //setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); +// +// var centerPanel = new JPanel(new GridLayout(0, 2, 20, 30)); +// centerPanel.setBackground(AppTheme.INSTANCE.getDarkControlBackground()); +// +//// centerPanel.add(Box.createHorizontalGlue()); +//// centerPanel.add(Box.createHorizontalGlue()); +// centerPanel.add(createLeftPanel()); +// centerPanel.add(createRightPanel()); +// //centerPanel.add(Box.createHorizontalGlue()); +//// centerPanel.add(Box.createHorizontalGlue()); +//// centerPanel.add(Box.createHorizontalGlue()); +// +// var containerBox = Box.createHorizontalBox(); +// containerBox.add(Box.createHorizontalGlue()); +// containerBox.add(centerPanel); +// containerBox.add(Box.createHorizontalGlue()); +// add(Box.createVerticalGlue()); +// add(containerBox); +// add(Box.createVerticalGlue()); + } + + +// public HomePanel() { +// super(null); +// setBackground(AppTheme.INSTANCE.getDarkControlBackground()); +// setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); +// +// var centerPanel = new JPanel(new GridLayout(1, 2)); +// centerPanel.setBackground(AppTheme.INSTANCE.getDarkControlBackground()); +// centerPanel.setAlignmentX(Component.CENTER_ALIGNMENT); +// +// var logoLabel = new JLabel("m"); +// logoLabel.setFont(new Font(Font.DIALOG, Font.BOLD, 128)); +// logoLabel.setAlignmentX(Component.CENTER_ALIGNMENT); +// +// var titleLabel = new JLabel("Muon"); +// titleLabel.setFont(new Font(Font.DIALOG, Font.BOLD, 32)); +// //titleLabel.setForeground(Color.DARK_GRAY); +// titleLabel.setAlignmentX(Component.LEFT_ALIGNMENT); +// +// var subTitleLabel = new JLabel("Modern SSH / SFTP client"); +// subTitleLabel.setFont(new Font(Font.DIALOG, Font.PLAIN, 14)); +// subTitleLabel.setAlignmentX(Component.LEFT_ALIGNMENT); +// subTitleLabel.setForeground(Color.DARK_GRAY); +// +// var versionLabel = new JLabel("v1.0.1"); +// versionLabel.setForeground(Color.DARK_GRAY); +// versionLabel.setFont(new Font(Font.DIALOG, Font.PLAIN, 14)); +// versionLabel.setAlignmentX(Component.LEFT_ALIGNMENT); +// +// var homePageLabel = new JLabel("muon.github.com"); +// homePageLabel.setForeground(Color.DARK_GRAY); +// homePageLabel.setFont(new Font(Font.DIALOG, Font.PLAIN, 14)); +// homePageLabel.setAlignmentX(Component.LEFT_ALIGNMENT); +// +// var vbox1 = Box.createVerticalBox(); +// vbox1.setAlignmentX(Component.CENTER_ALIGNMENT); +// //vbox1.add(logoLabel); +// vbox1.add(titleLabel); +// vbox1.add(Box.createRigidArea(new Dimension(10,5))); +// vbox1.add(subTitleLabel); +// vbox1.add(Box.createRigidArea(new Dimension(5,5))); +// vbox1.add(versionLabel); +// vbox1.add(Box.createRigidArea(new Dimension(5,5))); +// vbox1.add(homePageLabel); +// +// centerPanel.add(vbox1); +// +// var btn1=createIconButton1(FontIcon.RI_SERVER_FILL, "Connection manager", "Create and manage connections"); +// var btn2=createIconButton1(FontIcon.RI_TOOLS_FILL, "Settings", "Manage configurations"); +// +// var width=Math.max(btn1.getPreferredSize().width, btn2.getPreferredSize().width); +// var height=Math.max(btn1.getPreferredSize().height, btn2.getPreferredSize().height); +// +// btn1.setPreferredSize(new Dimension(width,height)); +// btn2.setPreferredSize(new Dimension(width,height)); +// +// btn1.setMinimumSize(new Dimension(width,height)); +// btn2.setMinimumSize(new Dimension(width,height)); +// +// btn1.setMaximumSize(new Dimension(width,height)); +// btn2.setMaximumSize(new Dimension(width,height)); +// +// var vbox2 = Box.createVerticalBox(); +// vbox2.add(btn1); +// vbox2.add(Box.createRigidArea(new Dimension(10, 10))); +// vbox2.add(btn2); +// centerPanel.add(vbox2); +// +// Box b2 = Box.createHorizontalBox(); +// b2.add(Box.createHorizontalGlue()); +// b2.add(centerPanel); +// b2.add(Box.createHorizontalGlue()); +// b2.setAlignmentX(Component.CENTER_ALIGNMENT); +// +// Box b1 = Box.createHorizontalBox(); +// b1.setAlignmentX(Component.CENTER_ALIGNMENT); +// b1.add(createIconButton(FontIcon.RI_BOX_3_FILL, "Connect")); +// b1.add(Box.createRigidArea(new Dimension(30, 20))); +// b1.add(createIconButton(FontIcon.RI_TOOLS_FILL, "Settings")); +// +//// b1.add(createIconLabel(FontIcon.RI_COMPUTER_FILL, 78f)); +//// b1.add(Box.createRigidArea(new Dimension(10, 20))); +//// b1.add(createIconLabel(FontIcon.RI_ARROW_LEFT_RIGHT_LINE, 32f)); +//// b1.add(Box.createRigidArea(new Dimension(10, 20))); +//// b1.add(createIconLabel(FontIcon.RI_SERVER_FILL, 78f)); +// +//// var btn2 = new JButton(); +//// btn2.setLayout(new BoxLayout(btn2, BoxLayout.Y_AXIS)); +//// btn2.add(createIconLabel(FontIcon.RI_SERVER_FILL, 78f)); +//// var lbl2 = new JLabel("Connect"); +//// lbl2.setAlignmentX(Component.CENTER_ALIGNMENT); +//// btn2.add(lbl2); +//// +//// var btn3 = new JButton(); +//// btn3.setLayout(new BoxLayout(btn2, BoxLayout.Y_AXIS)); +//// btn3.add(createIconLabel(FontIcon.RI_SERVER_FILL, 78f)); +//// var lbl3 = new JLabel("Settings"); +//// lbl3.setAlignmentX(Component.CENTER_ALIGNMENT); +//// btn2.add(lbl3); +//// +//// btn2.setBackground(AppTheme.INSTANCE.getHomePanelButtonColor()); +//// btn2.setForeground(Color.GRAY); +//// btn2.setFont(new Font(Font.DIALOG, Font.PLAIN, 14)); +//// btn2.putClientProperty("button.arc", 15); +//// btn2.setBorderPainted(false); +//// btn2.setBorder(new EmptyBorder(10, 20, 10, 20)); +//// btn2.setAlignmentX(Component.CENTER_ALIGNMENT); +// add(Box.createVerticalGlue()); +// //add(b1); +// add(b2); +//// add(Box.createRigidArea(new Dimension(0, 20))); +//// add(btn2); +// add(Box.createVerticalGlue()); +// } + + private JComponent createRightPanel(List sessions) { + var containerBox = Box.createVerticalBox(); + containerBox.setOpaque(true); + containerBox.setBackground(AppTheme.INSTANCE.getBackground()); + + var titleLabel = new JLabel("Recent sessions"); + titleLabel.setFont(new Font(Font.DIALOG, Font.BOLD, 16)); + titleLabel.setAlignmentX(Component.CENTER_ALIGNMENT); + containerBox.add(titleLabel); + + if (Objects.nonNull(sessions) && sessions.size() > 0) { + + var buttons = new JButton[sessions.size()]; + for (var i = 0; i < buttons.length; i++) { + var btn1 = createIconButton2(IconCode.RI_INSTANCE_LINE, sessions.get(i).getName(), sessions.get(i).getUser()); + buttons[i] = btn1; + } + + var width = 0; + var height = 0; + for (var button : + buttons) { + width = Math.max(button.getPreferredSize().width, width); + height = Math.max(button.getPreferredSize().height, height); + } + + var buttonSize = new Dimension(width, height); + + containerBox.add(Box.createRigidArea(new Dimension(10, 20))); + + for (var button : + buttons) { + button.setAlignmentX(Component.CENTER_ALIGNMENT); + button.setAlignmentY(Component.TOP_ALIGNMENT); + width = Math.max(button.getPreferredSize().width, width); + height = Math.max(button.getPreferredSize().height, height); + button.setPreferredSize(buttonSize); + button.setMaximumSize(buttonSize); + containerBox.add(button); + containerBox.add(Box.createRigidArea(new Dimension(10, 10))); + } + containerBox.add(Box.createRigidArea(new Dimension(10, 30))); + + } else { + var iconLabel = createIconLabel(IconCode.RI_FOLDER_FORBID_FILL, 128f); + iconLabel.setForeground(new Color(45, 45, 45)); + iconLabel.setAlignmentX(Component.CENTER_ALIGNMENT); + + var infoLabel = new JLabel("No recent sessions found"); + infoLabel.setForeground(AppTheme.INSTANCE.getLightForeground()); + infoLabel.setFont(new Font(Font.DIALOG, Font.PLAIN, 14)); + infoLabel.setAlignmentX(Component.CENTER_ALIGNMENT); + containerBox.add(Box.createRigidArea(new Dimension(30, 30))); + containerBox.add(iconLabel); + containerBox.add(Box.createRigidArea(new Dimension(30, 20))); + containerBox.add(infoLabel); + containerBox.add(Box.createRigidArea(new Dimension(10, 30))); + } + + + return containerBox; + } + + private JComponent createLeftPanel(ActionListener actionListener) { + var titleLabel = new JLabel("Muon"); + //titleLabel.setForeground(AppTheme.INSTANCE.getSelectionColor()); + titleLabel.setFont(new Font(Font.DIALOG, Font.BOLD, 32)); + titleLabel.setAlignmentX(Component.LEFT_ALIGNMENT); + titleLabel.setAlignmentY(Component.BOTTOM_ALIGNMENT); + + var versionLabel = new JLabel("v1.0.1"); + versionLabel.setForeground(AppTheme.INSTANCE.getLightForeground()); + versionLabel.setFont(new Font(Font.DIALOG, Font.PLAIN, 14)); + versionLabel.setAlignmentX(Component.LEFT_ALIGNMENT); + versionLabel.setAlignmentY(Component.BOTTOM_ALIGNMENT); + versionLabel.setBorder(new EmptyBorder(0, 5, 5, 0)); + + var titleBox = Box.createHorizontalBox(); + titleBox.setAlignmentX(Component.CENTER_ALIGNMENT); + titleBox.setAlignmentY(Component.TOP_ALIGNMENT); + titleBox.add(titleLabel); + titleBox.add(versionLabel); + + var subTitleLabel = new JLabel("Modern SSH / SFTP client"); + subTitleLabel.setFont(new Font(Font.DIALOG, Font.PLAIN, 14)); + subTitleLabel.setAlignmentX(Component.CENTER_ALIGNMENT); + subTitleLabel.setAlignmentY(Component.TOP_ALIGNMENT); + subTitleLabel.setForeground(AppTheme.INSTANCE.getLightForeground()); + + + var containerBox = Box.createVerticalBox(); + //containerBox.setOpaque(true); + //containerBox.setBackground(Color.RED); + //containerBox.setAlignmentY(Component.TOP_ALIGNMENT); + containerBox.setAlignmentX(Component.CENTER_ALIGNMENT); + //containerBox.add(Box.createRigidArea(new Dimension(0, 50))); + containerBox.add(titleBox); + //containerBox.add(Box.createRigidArea(new Dimension(0,0))); + containerBox.add(subTitleLabel); + //containerBox.add(versionLabel); + //containerBox.add(versionLabel); + + + var btn1 = createIconButton3(IconCode.RI_SERVER_FILL, "Session manager", "Create and manage connections"); + var btn2 = createIconButton3(IconCode.RI_SAFE_2_FILL, "Manage Keys", "Create and manage local keys"); + var btn3 = createIconButton3(IconCode.RI_TOOLS_FILL, "Settings", "Manage configurations"); + + btn1.addActionListener(actionListener); + + var buttons = new JButton[]{btn1, btn2, btn3}; + + var width = 0; + var height = 0; + for (var button : + buttons) { + width = Math.max(button.getPreferredSize().width, width); + height = Math.max(button.getPreferredSize().height, height); + } + + var buttonSize = new Dimension(width, height); + + containerBox.add(Box.createRigidArea(new Dimension(10, 20))); + + for (var button : + buttons) { + button.setAlignmentX(Component.CENTER_ALIGNMENT); + button.setAlignmentY(Component.TOP_ALIGNMENT); + width = Math.max(button.getPreferredSize().width, width); + height = Math.max(button.getPreferredSize().height, height); + button.setPreferredSize(buttonSize); + button.setMaximumSize(buttonSize); + containerBox.add(button); + containerBox.add(Box.createRigidArea(new Dimension(10, 10))); + } + containerBox.add(Box.createRigidArea(new Dimension(10, 30))); + + return containerBox; + } + + private JButton createIconButton(IconCode icon, String text) { + var button = new JButton(); + button.setLayout(new BoxLayout(button, BoxLayout.Y_AXIS)); + button.add(createIconLabel(icon, 78f)); + var lbl2 = new JLabel(text); + lbl2.setAlignmentX(Component.CENTER_ALIGNMENT); + button.add(lbl2); + + button.setBackground(AppTheme.INSTANCE.getHomePanelButtonColor()); + button.setForeground(Color.GRAY); + button.setFont(new Font(Font.DIALOG, Font.PLAIN, 14)); + button.putClientProperty("button.arc", 15); + button.setBorderPainted(false); + button.setBorder(new EmptyBorder(10, 20, 10, 20)); + button.setAlignmentX(Component.CENTER_ALIGNMENT); + + return button; + } + + private JButton createIconButton1(IconCode icon, String title, String subtitle) { + var hbox = Box.createHorizontalBox(); + + var titleLabel = new JLabel(title); + titleLabel.setFont(new Font(Font.DIALOG, Font.PLAIN, 14)); + + var vbox = Box.createVerticalBox(); + vbox.add(titleLabel); + vbox.add(Box.createRigidArea(new Dimension(10, 5))); + vbox.add(new JLabel(subtitle)); + vbox.add(Box.createRigidArea(new Dimension(10, 5))); + + hbox.add(createIconLabel(icon, 64f)); + hbox.add(Box.createRigidArea(new Dimension(10, 10))); + hbox.add(vbox); + hbox.add(Box.createRigidArea(new Dimension(10, 10))); + hbox.setAlignmentX(Component.LEFT_ALIGNMENT); + + var button = new JButton(); + button.setBorder(new EmptyBorder(10, 20, 10, 20)); + button.add(hbox); + button.setAlignmentX(Component.LEFT_ALIGNMENT); + + return button; + } + + private JButton createIconButton2(IconCode icon, String title, String subtitle) { + var hbox = Box.createHorizontalBox(); + + var titleLabel = new JLabel(title); + titleLabel.setFont(new Font(Font.DIALOG, Font.PLAIN, 14)); + + var vbox = Box.createVerticalBox(); + vbox.add(titleLabel); + vbox.add(Box.createRigidArea(new Dimension(0, 3))); + vbox.add(new JLabel(subtitle)); + + hbox.add(createIconLabel(icon, 32f)); + hbox.add(Box.createRigidArea(new Dimension(10, 5))); + hbox.add(vbox); + hbox.add(Box.createRigidArea(new Dimension(10, 5))); + hbox.setAlignmentX(Component.LEFT_ALIGNMENT); + + var button = new JButton(); + button.setBorder(new EmptyBorder(5, 20, 8, 20)); + button.add(hbox); + button.setAlignmentX(Component.LEFT_ALIGNMENT); + + return button; + } + + private JButton createIconButton3(IconCode icon, String title, String subtitle) { + var hbox = Box.createHorizontalBox(); + + var titleLabel = new JLabel(title); + titleLabel.setFont(new Font(Font.DIALOG, Font.PLAIN, 14)); + //titleLabel.setForeground(Color.DARK_GRAY); + + var subtitleLabel = new JLabel(subtitle); + subtitleLabel.setFont(new Font(Font.DIALOG, Font.PLAIN, 12)); + //subtitleLabel.setForeground(Color.DARK_GRAY); + + var vbox = Box.createVerticalBox(); + vbox.add(Box.createRigidArea(new Dimension(10, 3))); + vbox.add(titleLabel); + vbox.add(Box.createRigidArea(new Dimension(10, 3))); + vbox.add(subtitleLabel); + vbox.add(Box.createRigidArea(new Dimension(10, 5))); + + hbox.add(createIconLabel(icon, 42f)); + hbox.add(Box.createRigidArea(new Dimension(5, 0))); + hbox.add(vbox); + hbox.add(Box.createRigidArea(new Dimension(10, 0))); + hbox.setAlignmentX(Component.LEFT_ALIGNMENT); + + var button = new JButton(); + button.putClientProperty("button.arc", 10); + button.setBackground(AppTheme.INSTANCE.getBackground()); + button.setBorderPainted(false); + button.setBorder(new EmptyBorder(5, 10, 5, 20)); + button.add(hbox); + + return button; + } + + private JLabel createIconLabel(IconCode icon, Float size) { + var iconLabel = new JLabel(); + iconLabel.setBorder(new EmptyBorder(5, 0, 0, 0)); + iconLabel.setForeground(new Color(51, 51, 51)); + iconLabel.setFont(IconFont.getSharedInstance().getIconFont(size)); + iconLabel.setText(icon.getValue()); iconLabel.setAlignmentX(Component.CENTER_ALIGNMENT); - var btn2 = new JButton("Jdadasdasd"); - btn2.setUI(new FlatButtonUI()); - btn2.setAlignmentX(Component.CENTER_ALIGNMENT); - add(Box.createVerticalGlue()); - add(iconLabel); - add(Box.createRigidArea(new Dimension(0,10))); - add(btn2); - add(Box.createVerticalGlue()); + iconLabel.setAlignmentY(Component.CENTER_ALIGNMENT); + return iconLabel; } } diff --git a/app/src/main/java/muon/ui/widgets/SessionEditorPanel.java b/app/src/main/java/muon/ui/widgets/SessionEditorPanel.java new file mode 100644 index 00000000..c1d7c3fe --- /dev/null +++ b/app/src/main/java/muon/ui/widgets/SessionEditorPanel.java @@ -0,0 +1,397 @@ +package muon.ui.widgets; + +import muon.ui.styles.AppTheme; +import muon.ui.styles.FlatTreeRenderer; +import muon.util.IconCode; +import muon.util.IconFont; + +import javax.swing.*; +import javax.swing.border.EmptyBorder; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +public class SessionEditorPanel extends JPanel { + private JSplitPane splitPane; + + public SessionEditorPanel() { + super(new BorderLayout()); + splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); + splitPane.setContinuousLayout(true); + splitPane.setDividerSize(1); + splitPane.setOneTouchExpandable(false); + splitPane.setBackground(AppTheme.INSTANCE.getSplitPaneBackground()); + + var treeScroll = new JScrollPane(createSessionTree()); + treeScroll.setBorder(new EmptyBorder(0, 0, 0, 0)); + + var leftPanel = new JPanel(new BorderLayout()); + leftPanel.add(treeScroll); + leftPanel.add(createTreeTools(), BorderLayout.NORTH); + leftPanel.setBackground(AppTheme.INSTANCE.getBackground()); + + splitPane.setLeftComponent(leftPanel); + splitPane.setRightComponent(createSessionEditorPanel()); + splitPane.setDividerLocation(250); + + add(splitPane); + } + + private JButton createButton(IconCode iconCode) { + var button = new JButton(); + button.setContentAreaFilled(false); + button.setBorderPainted(false); + button.setBorder(new EmptyBorder(2, 5, 2, 5)); + button.setFont(IconFont.getSharedInstance().getIconFont(18)); + button.setText(iconCode.getValue()); + return button; + } + + private Component createTreeTools() { + var hbox1 = Box.createHorizontalBox(); + hbox1.setBorder( + new EmptyBorder(10, 5, 10, 5) + ); + hbox1.add(Box.createRigidArea(new Dimension(5, 0))); + hbox1.add(createButton(IconCode.RI_ADD_LINE)); + hbox1.add(Box.createRigidArea(new Dimension(5, 0))); + var txtSearch = new JTextField(); + hbox1.add(txtSearch); + hbox1.add(Box.createRigidArea(new Dimension(5, 0))); + hbox1.add(createButton(IconCode.RI_MORE_2_LINE)); + return hbox1; + } + + private JTree createSessionTree() { + var root = new DefaultMutableTreeNode("Sessions", true); + root.add(new DefaultMutableTreeNode("New session", true)); + var treeModel = new DefaultTreeModel(root, true); + var tree = new JTree(treeModel); + tree.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getButton() == MouseEvent.BUTTON1) { + var row = tree.getClosestRowForLocation(e.getX(), e.getY()); + tree.setSelectionRow(row); + if (row >= 0) { + var bounds = tree.getRowBounds(row); + if (bounds.contains(e.getX(), e.getY())) { + if (e.getX() < bounds.x + 40) { + if (tree.isExpanded(row)) { + tree.collapseRow(row); + } else { + tree.expandRow(row); + } + } + } + } + } + } + }); + var renderer = new FlatTreeRenderer(); + tree.setCellRenderer(renderer); + tree.setShowsRootHandles(false); + tree.setRowHeight(renderer.getPreferredHeight()); + tree.setRootVisible(true); + return tree; + } + + private JPanel createSessionEditorPanel() { + var panel = new JPanel(new GridBagLayout()); + panel.setBackground(AppTheme.INSTANCE.getBackground()); + + var nameLbl = new JLabel("Name"); + var txtName = new JTextField(); + + var gc = new GridBagConstraints(); + gc.insets = new Insets(10, 10, 10, 5); + panel.add(nameLbl, gc); + + gc = new GridBagConstraints(); + gc.gridx = 1; + gc.fill = GridBagConstraints.HORIZONTAL; + gc.insets = new Insets(10, 5, 10, 10); + gc.weightx = 1; + gc.gridwidth = 3; + panel.add(txtName, gc); + + gc = new GridBagConstraints(); + gc.gridy = 1; + gc.gridwidth = 4; + gc.fill = GridBagConstraints.BOTH; + gc.weightx = 1; + gc.weighty = 1; + gc.anchor = GridBagConstraints.PAGE_START; + + var tabbedPanel = new TabbedPanel( + false, + false, + new Color(52, 117, 233), + new Color(24, 24, 24), + new Color(52, 117, 233), + new Color(100, 100, 100), + new Color(31, 31, 31), + new Color(130, 130, 130), + new Color(180, 180, 180), + null, + Color.BLACK + ); + + tabbedPanel.addTab("Basic", null, createBasicPanel()); + tabbedPanel.addTab("Proxy", null, createBasicPanel()); + tabbedPanel.addTab("Jump hosts", null, createBasicPanel()); + tabbedPanel.addTab("Port forwarding", null, createBasicPanel()); + tabbedPanel.setSelectedIndex(0); + + panel.add(tabbedPanel, gc); + + gc = new GridBagConstraints(); + gc.gridy = 2; + gc.gridx = 1; + gc.gridwidth = 1; + gc.weightx = 1; + panel.add(new JLabel(), gc); + + gc = new GridBagConstraints(); + gc.insets = new Insets(10, 0, 10, 0); + gc.gridy = 2; + gc.gridx = 2; + gc.gridwidth = 1; + gc.weightx = 0; + panel.add(new JButton("Connect"), gc); + + gc = new GridBagConstraints(); + gc.gridy = 2; + gc.gridx = 3; + gc.gridwidth = 1; + gc.anchor = GridBagConstraints.LINE_END; + gc.insets = new Insets(10, 10, 10, 10); + + panel.add(new JButton("Cancel"), gc); + + return panel; + } + + private JPanel createBasicPanel() { + var panel = new JPanel(new GridBagLayout()); + panel.setBorder(new EmptyBorder(10, 10, 10, 10)); + panel.setBackground(AppTheme.INSTANCE.getBackground()); + + var lblHost = new JLabel("Host name", JLabel.RIGHT); + var lblPort = new JLabel("Port", JLabel.RIGHT); + var lblUserName = new JLabel("User name", JLabel.RIGHT); + var lblPassword = new JLabel("Password", JLabel.RIGHT); + var lblKeyFile = new JLabel("Key file", JLabel.RIGHT); + var lblRemoteFolder = new JLabel("Remote folder", JLabel.RIGHT); + var lblLocalFolder = new JLabel("Local folder", JLabel.RIGHT); + var lblCombinedMode = new JLabel("Show files and terminal in same tab", JLabel.LEFT); + var lblStartPage = new JLabel("Start page", JLabel.RIGHT); + + var txtHost = new JTextField(); + var txtPort = new JTextField(); + var txtUser = new JTextField(); + var txtPass = new JPasswordField(); + var txtKeyFile = new JTextField(); + var txtRemoteFolder = new JTextField(); + var txtLocalFolder = new JTextField(); + var swCombinedMode = new SwitchButton(); + var cmbStartPage = new JComboBox(new String[]{"SFTP+Terminal", "SFTP", "Terminal", "Port forwarding"}); + + var btnBrowseKey = new JButton("..."); + var btnBrowseFolder = new JButton("..."); + + var c = 0; + var insets = new Insets(5, 5, 5, 5); + + var gc = new GridBagConstraints(); + gc.gridx = 0; + gc.anchor = GridBagConstraints.LINE_END; + gc.gridy = c; + gc.insets = insets; + panel.add(lblHost, gc); + + gc = new GridBagConstraints(); + gc.gridx = 1; + gc.gridy = c; + gc.fill = GridBagConstraints.HORIZONTAL; + gc.gridwidth = 2; + gc.weightx = 1; + gc.insets = insets; + panel.add(txtHost, gc); + + c++; + + gc = new GridBagConstraints(); + gc.gridx = 0; + gc.anchor = GridBagConstraints.LINE_END; + gc.gridy = c; + gc.insets = insets; + panel.add(lblPort, gc); + + gc = new GridBagConstraints(); + gc.gridx = 1; + gc.gridy = c; + gc.fill = GridBagConstraints.HORIZONTAL; + gc.gridwidth = 2; + gc.weightx = 1; + gc.insets = insets; + panel.add(txtPort, gc); + + c++; + + gc = new GridBagConstraints(); + gc.gridx = 0; + gc.anchor = GridBagConstraints.LINE_END; + gc.gridy = c; + gc.insets = insets; + panel.add(lblUserName, gc); + + gc = new GridBagConstraints(); + gc.gridx = 1; + gc.gridy = c; + gc.fill = GridBagConstraints.HORIZONTAL; + gc.gridwidth = 2; + gc.weightx = 1; + gc.insets = insets; + panel.add(txtUser, gc); + + c++; + + gc = new GridBagConstraints(); + gc.gridx = 0; + gc.anchor = GridBagConstraints.LINE_END; + gc.gridy = c; + gc.insets = insets; + panel.add(lblPassword, gc); + + gc = new GridBagConstraints(); + gc.gridx = 1; + gc.gridy = c; + gc.fill = GridBagConstraints.HORIZONTAL; + gc.gridwidth = 2; + gc.weightx = 1; + gc.insets = insets; + panel.add(txtPass, gc); + + c++; + + gc = new GridBagConstraints(); + gc.gridx = 0; + gc.anchor = GridBagConstraints.LINE_END; + gc.gridy = c; + gc.insets = insets; + panel.add(lblKeyFile, gc); + + gc = new GridBagConstraints(); + gc.gridx = 1; + gc.gridy = c; + gc.fill = GridBagConstraints.HORIZONTAL; + gc.gridwidth = 1; + gc.weightx = 1; + gc.insets = insets; + panel.add(txtKeyFile, gc); + + gc = new GridBagConstraints(); + gc.gridx = 2; + gc.gridy = c; + gc.gridwidth = 1; + gc.insets = insets; + panel.add(btnBrowseKey, gc); + + c++; + + gc = new GridBagConstraints(); + gc.gridx = 0; + gc.anchor = GridBagConstraints.LINE_END; + gc.gridy = c; + gc.insets = insets; + panel.add(lblRemoteFolder, gc); + + gc = new GridBagConstraints(); + gc.gridx = 1; + gc.gridy = c; + gc.fill = GridBagConstraints.HORIZONTAL; + gc.gridwidth = 2; + gc.weightx = 1; + gc.insets = insets; + panel.add(txtRemoteFolder, gc); + + c++; + + gc = new GridBagConstraints(); + gc.gridx = 0; + gc.anchor = GridBagConstraints.LINE_END; + gc.gridy = c; + gc.insets = insets; + panel.add(lblLocalFolder, gc); + + gc = new GridBagConstraints(); + gc.gridx = 1; + gc.gridy = c; + gc.fill = GridBagConstraints.HORIZONTAL; + gc.gridwidth = 1; + gc.weightx = 1; + gc.insets = insets; + panel.add(txtLocalFolder, gc); + + gc = new GridBagConstraints(); + gc.gridx = 2; + gc.gridy = c; + gc.gridwidth = 1; + gc.insets = insets; + panel.add(btnBrowseFolder, gc); + + c++; + + gc = new GridBagConstraints(); + gc.gridx = 1; + gc.gridwidth = 1; + gc.weightx = 1; + gc.anchor = GridBagConstraints.LINE_START; + gc.fill = GridBagConstraints.HORIZONTAL; + gc.gridy = c; + gc.insets = insets; + panel.add(lblCombinedMode, gc); + + gc = new GridBagConstraints(); + gc.gridx = 2; + gc.gridy = c; + gc.gridwidth = 1; + gc.insets = insets; + panel.add(swCombinedMode, gc); + + c++; + + gc = new GridBagConstraints(); + gc.gridx = 0; + gc.anchor = GridBagConstraints.LINE_END; + gc.gridy = c; + gc.insets = insets; + panel.add(lblStartPage, gc); + + gc = new GridBagConstraints(); + gc.gridx = 1; + gc.gridy = c; + gc.fill = GridBagConstraints.HORIZONTAL; + gc.gridwidth = 2; + gc.weightx = 1; + gc.insets = insets; + panel.add(cmbStartPage, gc); + + c++; + + gc = new GridBagConstraints(); + gc.gridx = 0; + gc.gridy = c; + gc.gridwidth = 2; + gc.fill = GridBagConstraints.BOTH; + gc.anchor = GridBagConstraints.PAGE_START; + gc.weightx = 1; + gc.weighty = 1; + panel.add(new JLabel(), gc); + + return panel; + } +} diff --git a/app/src/main/java/muon/ui/widgets/SessionManagerDialog.java b/app/src/main/java/muon/ui/widgets/SessionManagerDialog.java new file mode 100644 index 00000000..f8faa1e8 --- /dev/null +++ b/app/src/main/java/muon/ui/widgets/SessionManagerDialog.java @@ -0,0 +1,22 @@ +package muon.ui.widgets; + +import muon.ui.styles.AppTheme; + +import javax.swing.*; +import java.awt.*; + +public class SessionManagerDialog extends JDialog { + public SessionManagerDialog(Window window) { + super(window); + setTitle("Session manager"); + setModal(true); + setSize(800, 600); + setLocationRelativeTo(window); + setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); + + getContentPane().setBackground( + AppTheme.INSTANCE.getDarkControlBackground()); + + add(new SessionEditorPanel()); + } +} diff --git a/app/src/main/java/muon/ui/widgets/SwitchButton.java b/app/src/main/java/muon/ui/widgets/SwitchButton.java new file mode 100644 index 00000000..1a482ba0 --- /dev/null +++ b/app/src/main/java/muon/ui/widgets/SwitchButton.java @@ -0,0 +1,21 @@ +package muon.ui.widgets; + +import muon.util.IconCode; +import muon.util.IconFont; + +import javax.swing.*; + +public class SwitchButton extends JLabel { + private IconCode onIcon, offIcon; + + public SwitchButton() { + this(IconCode.RI_TOGGLE_FILL, IconCode.RI_TOGGLE_LINE, 32); + } + + public SwitchButton(IconCode onIcon, IconCode offIcon, int size) { + setFont(IconFont.getSharedInstance().getIconFont(size)); + this.onIcon = onIcon; + this.offIcon = offIcon; + setText(onIcon.getValue()); + } +} diff --git a/app/src/main/java/muon/ui/widgets/TabItem.java b/app/src/main/java/muon/ui/widgets/TabItem.java index d912d7e8..f0f59db4 100644 --- a/app/src/main/java/muon/ui/widgets/TabItem.java +++ b/app/src/main/java/muon/ui/widgets/TabItem.java @@ -1,6 +1,6 @@ package muon.ui.widgets; -import muon.util.FontIcon; +import muon.util.IconCode; import muon.util.IconFont; import javax.swing.*; @@ -23,10 +23,10 @@ public class TabItem extends JComponent { private boolean isStretchable, isCloseButtonHidden; private Color selectionColor, backgroundColor, iconColor, closeButtonColor, selectionBackground, titleColor, selectedTitleColor; private Border selectedBorder, unselectedBorder; - private FontIcon titleIcon, closeIcon; + private IconCode titleIcon, closeIcon; private ActionListener tabClicked, closeClicked; - public TabItem(FontIcon titleIcon, FontIcon closeIcon, + public TabItem(IconCode titleIcon, IconCode closeIcon, Color selectionColor, boolean isSelected, Color backgroundColor, boolean hideCloseButton, Color iconColor, Color closeButtonColor, @@ -54,8 +54,8 @@ public TabItem(FontIcon titleIcon, FontIcon closeIcon, this.tabIconLabel.setFont(IconFont.getSharedInstance().getIconFont(18.0f)); } this.tabTitle = new JLabel(); - this.tabTitle.setMinimumSize(new Dimension(0, 0)); this.tabTitle.setFont(new Font(Font.DIALOG, Font.PLAIN, 12)); + this.tabTitle.setMinimumSize(new Dimension(0, 30)); this.tabTitle.setBorder(new EmptyBorder(0, 10, 2, 10)); if (Objects.nonNull(closeIcon)) { this.tabCloseButton = new JLabel(); @@ -75,14 +75,22 @@ public void mouseClicked(MouseEvent e) { setOpaque(true); if (isStretchable) { setLayout(new BorderLayout(10, 10)); - add(tabIconLabel, BorderLayout.WEST); + if(Objects.nonNull(tabIconLabel)){ + add(tabIconLabel, BorderLayout.WEST); + } add(tabTitle); - add(tabCloseButton, BorderLayout.EAST); + if(Objects.nonNull(tabCloseButton)){ + add(tabCloseButton, BorderLayout.EAST); + } } else { setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); - add(tabIconLabel); + if(Objects.nonNull(tabIconLabel)){ + add(tabIconLabel); + } add(tabTitle); - add(tabCloseButton); + if(Objects.nonNull(tabCloseButton)){ + add(tabCloseButton); + } } setSelected(isSelected); diff --git a/app/src/main/java/muon/ui/widgets/TabbedPanel.java b/app/src/main/java/muon/ui/widgets/TabbedPanel.java index 4e462b9e..0c719a8b 100644 --- a/app/src/main/java/muon/ui/widgets/TabbedPanel.java +++ b/app/src/main/java/muon/ui/widgets/TabbedPanel.java @@ -1,11 +1,10 @@ package muon.ui.widgets; -import muon.util.FontIcon; +import muon.util.IconCode; import javax.swing.*; import javax.swing.border.MatteBorder; import java.awt.*; -import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -16,7 +15,7 @@ public class TabbedPanel extends JPanel { private Color selectionColor, backgroundColor, iconColor, closeButtonColor, selectionBackground, titleColor, selectedTitleColor; - private FontIcon titleIcon, closeIcon; + private IconCode closeIcon; private Box tabHolder; private CardLayout cardLayout; private JPanel cardPanel; @@ -32,8 +31,7 @@ public TabbedPanel(boolean isStretchable, Color selectionBackground, Color titleColor, Color selectedTitleColor, - FontIcon titleIcon, - FontIcon closeIcon, + IconCode closeIcon, Color tabBorderColor) { super(new BorderLayout(), true); this.isStretchable = isStretchable; @@ -45,7 +43,6 @@ public TabbedPanel(boolean isStretchable, this.selectionBackground = selectionBackground; this.titleColor = titleColor; this.selectedTitleColor = selectedTitleColor; - this.titleIcon = titleIcon; this.closeIcon = closeIcon; this.tabListeners = Collections.synchronizedList(new ArrayList<>()); @@ -70,7 +67,7 @@ public TabbedPanel(boolean isStretchable, } - public void addTab(String tabTitle, FontIcon tabIcon, Component body) { + public void addTab(String tabTitle, IconCode tabIcon, Component body) { var tab = new TabItem(tabIcon, this.closeIcon, selectionColor, true, backgroundColor, isCloseButtonHidden, diff --git a/app/src/main/java/muon/util/AppUtils.java b/app/src/main/java/muon/util/AppUtils.java new file mode 100644 index 00000000..eb31e0eb --- /dev/null +++ b/app/src/main/java/muon/util/AppUtils.java @@ -0,0 +1,24 @@ +package muon.util; + +import java.awt.*; + +public class AppUtils { + public static Dimension calculateDefaultWindowSize() { + Insets inset = Toolkit.getDefaultToolkit().getScreenInsets( + GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice().getDefaultConfiguration()); + + Dimension screenD = Toolkit.getDefaultToolkit().getScreenSize(); + + int screenWidth = screenD.width - inset.left - inset.right; + int screenHeight = screenD.height - inset.top - inset.bottom; + + int width = (screenWidth * 80) / 100; + int height = (screenHeight * 80) / 100; + + width = Math.min(width, 900); + height = Math.min(height, 768); + + return new Dimension(width, height); + } +} diff --git a/app/src/main/java/muon/util/FontIcon.java b/app/src/main/java/muon/util/FontIcon.java deleted file mode 100644 index ba0e8c68..00000000 --- a/app/src/main/java/muon/util/FontIcon.java +++ /dev/null @@ -1,23 +0,0 @@ -package muon.util; - -public enum FontIcon { - RI_ADD_LINE("\uea13"), - RI_MENU_LINE("\uef3e"), - RI_INSTANCE_LINE("\uf383"), - RI_ARROW_LEFT_LINE("\uea60"), - RI_ARROW_RIGHT_LINE("\uea6c"), - RI_ARROW_UP_LINE("\uea76"), - RI_LOOP_RIGHT_LINE("\uf33f"), - RI_MORE_2_LINE("\uef77"), - RI_CLOSE_LINE("\ueb99"); - - public String getValue() { - return value; - } - - private FontIcon(String value) { - this.value = value; - } - - private String value; -} diff --git a/app/src/main/java/muon/util/IconCode.java b/app/src/main/java/muon/util/IconCode.java new file mode 100644 index 00000000..49a1b904 --- /dev/null +++ b/app/src/main/java/muon/util/IconCode.java @@ -0,0 +1,40 @@ +package muon.util; + +public enum IconCode { + RI_ADD_LINE("\uea13"), + RI_MENU_LINE("\uef3e"), + RI_INSTANCE_LINE("\uf383"), + RI_ARROW_LEFT_LINE("\uea60"), + RI_ARROW_RIGHT_LINE("\uea6c"), + RI_ARROW_UP_LINE("\uea76"), + RI_LOOP_RIGHT_LINE("\uf33f"), + RI_MORE_2_LINE("\uef77"), + RI_CLOSE_LINE("\ueb99"), + RI_COMPUTER_FILL("\uEBC9"), + RI_ARROW_LEFT_RIGHT_LINE("\uEA62"), + RI_CLOUD_FILL("\uEB9C"), + RI_DATABASE_2_FILL("\uEC15"), + RI_TOOLS_FILL("\uF21A"), + RI_BOX_3_FILL("\uF2F4"), + RI_FOLDER_FORBID_FILL("\uED62"), + RI_SAFE_2_FILL("\uF0A8"), + RI_FOLDER_FILL("\uED61"), + RI_FOLDER_OPEN_FILL("\uED6F"), + RI_ARROW_RIGHT_S_LINE("\uEA6E"), + RI_ARROW_DOWN_S_LINE("\uEA4E"), + RI_TOGGLE_LINE("\uF219"), + RI_TOGGLE_FILL("\uF218"), + RI_FOLDER_2_LINE("\uED52"), + RI_FOLDER_LINE("\uED6A"), + RI_SERVER_FILL("\uF0DF"); + + public String getValue() { + return value; + } + + private IconCode(String value) { + this.value = value; + } + + private String value; +}