From 40c508e90823a92cd6da1542b50b5832d16fc6ee Mon Sep 17 00:00:00 2001 From: Subhra Das Gupta Date: Fri, 5 Jan 2024 08:48:50 +0530 Subject: [PATCH] flatlaf integration --- app/pom.xml | 15 +- app/src/main/java/muon/App.java | 15 +- .../muon/screens/appwin/MainContainer.java | 109 ++++++---- .../filebrowser/AbstractFileBrowserView.java | 140 +++++++------ .../tabs/filebrowser/DualPaneFileBrowser.java | 171 +++++++++++----- .../FolderViewTableCellRenderer.java | 34 +++- .../transfer/foreground/FileListRenderer.java | 42 ++-- .../ForegroundTransferProgressPanel.java | 2 +- .../foreground/TransferConfirmPanel.java | 56 ++---- .../transfer/foreground/TransferDialog.java | 103 ++++++++++ .../foreground/TransferProgressPanel.java | 20 +- .../foreground/TransferRetryPanel.java | 15 +- .../terminal/CustomizedSettingsProvider.java | 4 +- .../appwin/tabs/terminal/TabbedTerminal.java | 124 +++++++----- .../screens/sessionmgr/SessionEditor.java | 33 +-- .../screens/sessionmgr/SessionManager.java | 3 +- .../screens/sessionmgr/SessionTreePanel.java | 134 +++++-------- .../java/muon/service/SftpUploadTask.java | 2 +- app/src/main/java/muon/styles/AppTheme.java | 188 +++++++++--------- .../java/muon/styles/FlatLookAndFeel.java | 2 +- .../java/muon/styles/FlatTreeRenderer.java | 99 ++------- app/src/main/java/muon/util/AppUtils.java | 21 ++ app/src/main/resources/icons/add-line.svg | 1 + .../resources/icons/arrow_back_black_24dp.svg | 1 + .../icons/arrow_forward_black_24dp.svg | 1 + .../icons/arrow_upward_black_24dp.svg | 1 + .../resources/icons/autorenew_black_24dp.svg | 1 + .../main/resources/icons/database-2-line.svg | 1 + .../resources/icons/delete-bin-6-fill.svg | 1 + app/src/main/resources/icons/file-2-fill.svg | 1 + .../main/resources/icons/file-add-fill.svg | 1 + .../main/resources/icons/file-copy-2-fill.svg | 1 + .../main/resources/icons/folder-add-fill.svg | 1 + app/src/main/resources/icons/folder-fill.svg | 1 + app/src/main/resources/icons/history-line.svg | 1 + .../main/resources/icons/home_black_24dp.svg | 1 + app/src/main/resources/icons/install-fill.svg | 1 + app/src/main/resources/icons/key-fill.svg | 1 + .../resources/icons/language_black_24dp.svg | 1 + .../resources/icons/laptop_black_24dp.svg | 1 + .../resources/icons/more_vert_black_24dp.svg | 1 + .../resources/icons/refresh_black_24dp.svg | 1 + .../resources/icons/search_black_24dp.svg | 1 + .../main/resources/icons/swap-box-fill.svg | 1 + .../main/resources/icons/sync_black_24dp.svg | 1 + .../resources/icons/terminal-box-fill.svg | 1 + .../main/resources/icons/uninstall-fill.svg | 1 + app/target/classes/icons/add-line.svg | 1 + .../classes/icons/arrow_back_black_24dp.svg | 1 + .../icons/arrow_forward_black_24dp.svg | 1 + .../classes/icons/arrow_upward_black_24dp.svg | 1 + .../classes/icons/autorenew_black_24dp.svg | 1 + app/target/classes/icons/database-2-line.svg | 1 + .../classes/icons/delete-bin-6-fill.svg | 1 + app/target/classes/icons/file-2-fill.svg | 1 + app/target/classes/icons/file-add-fill.svg | 1 + app/target/classes/icons/file-copy-2-fill.svg | 1 + app/target/classes/icons/folder-add-fill.svg | 1 + app/target/classes/icons/folder-fill.svg | 1 + app/target/classes/icons/history-line.svg | 1 + app/target/classes/icons/home_black_24dp.svg | 1 + app/target/classes/icons/install-fill.svg | 1 + app/target/classes/icons/key-fill.svg | 1 + .../classes/icons/language_black_24dp.svg | 1 + .../classes/icons/laptop_black_24dp.svg | 1 + .../classes/icons/more_vert_black_24dp.svg | 1 + .../classes/icons/refresh_black_24dp.svg | 1 + .../classes/icons/search_black_24dp.svg | 1 + app/target/classes/icons/swap-box-fill.svg | 1 + app/target/classes/icons/sync_black_24dp.svg | 1 + .../classes/icons/terminal-box-fill.svg | 1 + app/target/classes/icons/uninstall-fill.svg | 1 + .../surefire-reports/TEST-muon.AppTest.xml | 10 +- app/target/surefire-reports/muon.AppTest.txt | 2 +- 74 files changed, 804 insertions(+), 590 deletions(-) create mode 100644 app/src/main/java/muon/screens/appwin/tabs/filebrowser/transfer/foreground/TransferDialog.java create mode 100644 app/src/main/resources/icons/add-line.svg create mode 100644 app/src/main/resources/icons/arrow_back_black_24dp.svg create mode 100644 app/src/main/resources/icons/arrow_forward_black_24dp.svg create mode 100644 app/src/main/resources/icons/arrow_upward_black_24dp.svg create mode 100644 app/src/main/resources/icons/autorenew_black_24dp.svg create mode 100644 app/src/main/resources/icons/database-2-line.svg create mode 100644 app/src/main/resources/icons/delete-bin-6-fill.svg create mode 100644 app/src/main/resources/icons/file-2-fill.svg create mode 100644 app/src/main/resources/icons/file-add-fill.svg create mode 100644 app/src/main/resources/icons/file-copy-2-fill.svg create mode 100644 app/src/main/resources/icons/folder-add-fill.svg create mode 100644 app/src/main/resources/icons/folder-fill.svg create mode 100644 app/src/main/resources/icons/history-line.svg create mode 100644 app/src/main/resources/icons/home_black_24dp.svg create mode 100644 app/src/main/resources/icons/install-fill.svg create mode 100644 app/src/main/resources/icons/key-fill.svg create mode 100644 app/src/main/resources/icons/language_black_24dp.svg create mode 100644 app/src/main/resources/icons/laptop_black_24dp.svg create mode 100644 app/src/main/resources/icons/more_vert_black_24dp.svg create mode 100644 app/src/main/resources/icons/refresh_black_24dp.svg create mode 100644 app/src/main/resources/icons/search_black_24dp.svg create mode 100644 app/src/main/resources/icons/swap-box-fill.svg create mode 100644 app/src/main/resources/icons/sync_black_24dp.svg create mode 100644 app/src/main/resources/icons/terminal-box-fill.svg create mode 100644 app/src/main/resources/icons/uninstall-fill.svg create mode 100644 app/target/classes/icons/add-line.svg create mode 100644 app/target/classes/icons/arrow_back_black_24dp.svg create mode 100644 app/target/classes/icons/arrow_forward_black_24dp.svg create mode 100644 app/target/classes/icons/arrow_upward_black_24dp.svg create mode 100644 app/target/classes/icons/autorenew_black_24dp.svg create mode 100644 app/target/classes/icons/database-2-line.svg create mode 100644 app/target/classes/icons/delete-bin-6-fill.svg create mode 100644 app/target/classes/icons/file-2-fill.svg create mode 100644 app/target/classes/icons/file-add-fill.svg create mode 100644 app/target/classes/icons/file-copy-2-fill.svg create mode 100644 app/target/classes/icons/folder-add-fill.svg create mode 100644 app/target/classes/icons/folder-fill.svg create mode 100644 app/target/classes/icons/history-line.svg create mode 100644 app/target/classes/icons/home_black_24dp.svg create mode 100644 app/target/classes/icons/install-fill.svg create mode 100644 app/target/classes/icons/key-fill.svg create mode 100644 app/target/classes/icons/language_black_24dp.svg create mode 100644 app/target/classes/icons/laptop_black_24dp.svg create mode 100644 app/target/classes/icons/more_vert_black_24dp.svg create mode 100644 app/target/classes/icons/refresh_black_24dp.svg create mode 100644 app/target/classes/icons/search_black_24dp.svg create mode 100644 app/target/classes/icons/swap-box-fill.svg create mode 100644 app/target/classes/icons/sync_black_24dp.svg create mode 100644 app/target/classes/icons/terminal-box-fill.svg create mode 100644 app/target/classes/icons/uninstall-fill.svg diff --git a/app/pom.xml b/app/pom.xml index 93484ad0..c7779291 100644 --- a/app/pom.xml +++ b/app/pom.xml @@ -40,7 +40,7 @@ 1.7.30 - + com.fasterxml.jackson.core jackson-databind @@ -137,6 +137,17 @@ annotations 20.1.0 + + com.formdev + flatlaf + 3.2 + + + + com.formdev + flatlaf-extras + 3.2 + diff --git a/app/src/main/java/muon/App.java b/app/src/main/java/muon/App.java index 22135371..f2e8f8e8 100644 --- a/app/src/main/java/muon/App.java +++ b/app/src/main/java/muon/App.java @@ -1,5 +1,7 @@ package muon; +import com.formdev.flatlaf.FlatDarkLaf; +import com.formdev.flatlaf.themes.FlatMacDarkLaf; import muon.screens.appwin.MainContainer; import muon.screens.dialogs.BannerDialog; import muon.screens.dialogs.UserInputDialog; @@ -11,6 +13,7 @@ import muon.widgets.CustomFrame; import javax.swing.*; +import java.awt.*; import java.lang.reflect.InvocationTargetException; /** @@ -42,7 +45,17 @@ public static JFrame getAppWindow() { public static void main(String[] args) throws InterruptedException, InvocationTargetException, UnsupportedLookAndFeelException, ClassNotFoundException, InstantiationException, IllegalAccessException { System.setProperty("sun.java2d.metal", "false"); System.setProperty("apple.awt.application.appearance", "system"); - UIManager.setLookAndFeel(new FlatLookAndFeel()); + + FlatMacDarkLaf.setup(); + //UIManager.setLookAndFeel(new FlatLookAndFeel()); + UIManager.put("SplitPaneDivider.style","plain"); + UIManager.put("Tree.showDefaultIcons",true); + UIManager.put("Tree.rendererMargins",5); + UIManager.put("Tree.showsRootHandles",true); + UIManager.put("Tree.rendererMargins",5); + UIManager.put("Tree.leftChildIndent",5); + UIManager.put("Tree.rightChildIndent",5); + var isWindows = "windows".equalsIgnoreCase(System.getProperty("os.name")); diff --git a/app/src/main/java/muon/screens/appwin/MainContainer.java b/app/src/main/java/muon/screens/appwin/MainContainer.java index 837caf19..c049f396 100644 --- a/app/src/main/java/muon/screens/appwin/MainContainer.java +++ b/app/src/main/java/muon/screens/appwin/MainContainer.java @@ -1,5 +1,6 @@ package muon.screens.appwin; +import com.formdev.flatlaf.extras.FlatSVGIcon; import muon.AppContext; import muon.exceptions.AuthenticationException; import muon.screens.appwin.tabs.filebrowser.DualPaneFileBrowser; @@ -14,10 +15,11 @@ import javax.swing.border.*; import java.awt.*; import java.awt.event.*; +import java.io.IOException; import java.util.concurrent.atomic.AtomicBoolean; public class MainContainer extends JPanel implements AppWin { - private JPanel contentPanel; + //private JPanel contentPanel; private DualPaneFileBrowser dualPaneFileBrowser; private TabbedTerminal tabbedTerminal; private AtomicBoolean init = new AtomicBoolean(false); @@ -25,23 +27,44 @@ public class MainContainer extends JPanel implements AppWin { private JPasswordField txtPassword; private JButton btnPassword; + private ImageIcon createIcon(String name, int size) { + FlatSVGIcon.ColorFilter filter = new FlatSVGIcon.ColorFilter(); + filter.add(Color.BLACK, Color.GRAY); + FlatSVGIcon icon = null; + try { + icon = new FlatSVGIcon(getClass().getResourceAsStream("/icons/" + name)); + icon.setColorFilter(filter); + return icon.derive(size, size); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + public MainContainer() { super(new CardLayout()); + setBorder(new MatteBorder(1, 0, 0, 0, UIManager.getColor("TableHeader.bottomSeparatorColor"))); + var tabs = new JTabbedPane(); + tabs.setTabPlacement(JTabbedPane.BOTTOM); dualPaneFileBrowser = new DualPaneFileBrowser(this); tabbedTerminal = new TabbedTerminal(); - contentPanel = new JPanel(new CardLayout()); - contentPanel.add(dualPaneFileBrowser, "FILES"); - contentPanel.add(tabbedTerminal, "TERM"); + tabs.addTab("File Browser", createIcon("folder-fill.svg", 16), dualPaneFileBrowser); + tabs.addTab("Remote Terminal", createIcon("terminal-box-fill.svg", 16), tabbedTerminal); + tabs.addTab("Port Forwarding", createIcon("swap-box-fill.svg", 16), new JPanel()); + tabs.addTab("Key Manager", createIcon("key-fill.svg", 16), new JPanel()); - var panel = new JPanel(new BorderLayout()); - panel.add(contentPanel); - panel.add(createBottomTabs(), BorderLayout.SOUTH); +// contentPanel = new JPanel(new CardLayout()); +// contentPanel.add(dualPaneFileBrowser, "FILES"); +// contentPanel.add(tabbedTerminal, "TERM"); +// +// var panel = new JPanel(new BorderLayout()); +// panel.add(contentPanel); +// panel.add(createBottomTabs(), BorderLayout.SOUTH); this.add(createProgressPanel(), "PROGRESS"); this.add(createPasswordPanel(), "PASSWORD"); - this.add(panel, "CONTENT"); + this.add(tabs, "CONTENT"); this.addComponentListener(new ComponentAdapter() { @Override @@ -64,7 +87,7 @@ public void componentResized(ComponentEvent e) { private void initContent() { ((CardLayout) this.getLayout()).show(this, "CONTENT"); - ((CardLayout) contentPanel.getLayout()).show(contentPanel, "FILES"); +// ((CardLayout) contentPanel.getLayout()).show(contentPanel, "FILES"); revalidate(); repaint(); dualPaneFileBrowser.init(); @@ -83,40 +106,40 @@ private void loadInitialSessionContext() { }); } - private Container createBottomTabs() { - String[] str = new String[]{"FILES", "TERM"}; - ActionListener tabSelection = e -> { - for (var i = 0; i < tabs.length; i++) { - tabs[i].setSelected(e.getSource() == tabs[i]); - if (e.getSource() == tabs[i] && i < str.length) { - ((CardLayout) contentPanel.getLayout()).show(contentPanel, str[i]); - } - } - }; - - var box = Box.createHorizontalBox(); - box.setOpaque(true); - box.setBackground(AppTheme.INSTANCE.getDarkControlBackground()); - - var btnFiles = new BottomTabItem(IconCode.RI_FOLDER_FILL, "File Browser", tabSelection); - var btnTerminal = new BottomTabItem(IconCode.RI_TERMINAL_BOX_FILL, "Remote Terminal", tabSelection); - var btnPortFwd = new BottomTabItem(IconCode.RI_SWAP_BOX_FILL, "Port Forwarding", tabSelection); - var btnKeyMgr = new BottomTabItem(IconCode.RI_KEY_FILL, "Key Manager", tabSelection); - - tabs = new BottomTabItem[]{btnFiles, btnTerminal, btnPortFwd, btnKeyMgr}; - - btnFiles.setBackground(AppTheme.INSTANCE.getBackground()); - //AppUtils.makeEqualSize(btnFiles, btnTerminal, btnPortFwd, btnKeyMgr); - - box.add(btnFiles); - box.add(btnTerminal); - box.add(btnPortFwd); - box.add(btnKeyMgr); - box.add(Box.createHorizontalGlue()); - - box.setBorder(new MatteBorder(1, 0, 0, 0, AppTheme.INSTANCE.getButtonBorderColor())); - return box; - } +// private Container createBottomTabs() { +// String[] str = new String[]{"FILES", "TERM"}; +// ActionListener tabSelection = e -> { +// for (var i = 0; i < tabs.length; i++) { +// tabs[i].setSelected(e.getSource() == tabs[i]); +// if (e.getSource() == tabs[i] && i < str.length) { +// ((CardLayout) contentPanel.getLayout()).show(contentPanel, str[i]); +// } +// } +// }; +// +// var box = Box.createHorizontalBox(); +// box.setOpaque(true); +// box.setBackground(AppTheme.INSTANCE.getDarkControlBackground()); +// +// var btnFiles = new BottomTabItem(IconCode.RI_FOLDER_FILL, "File Browser", tabSelection); +// var btnTerminal = new BottomTabItem(IconCode.RI_TERMINAL_BOX_FILL, "Remote Terminal", tabSelection); +// var btnPortFwd = new BottomTabItem(IconCode.RI_SWAP_BOX_FILL, "Port Forwarding", tabSelection); +// var btnKeyMgr = new BottomTabItem(IconCode.RI_KEY_FILL, "Key Manager", tabSelection); +// +// tabs = new BottomTabItem[]{btnFiles, btnTerminal, btnPortFwd, btnKeyMgr}; +// +// btnFiles.setBackground(AppTheme.INSTANCE.getBackground()); +// //AppUtils.makeEqualSize(btnFiles, btnTerminal, btnPortFwd, btnKeyMgr); +// +// box.add(btnFiles); +// box.add(btnTerminal); +// box.add(btnPortFwd); +// box.add(btnKeyMgr); +// box.add(Box.createHorizontalGlue()); +// +// box.setBorder(new MatteBorder(1, 0, 0, 0, AppTheme.INSTANCE.getButtonBorderColor())); +// return box; +// } private JPanel createPasswordPanel() { var lbl = new JLabel("Unlock with master password"); diff --git a/app/src/main/java/muon/screens/appwin/tabs/filebrowser/AbstractFileBrowserView.java b/app/src/main/java/muon/screens/appwin/tabs/filebrowser/AbstractFileBrowserView.java index baddc22a..e65bdf99 100644 --- a/app/src/main/java/muon/screens/appwin/tabs/filebrowser/AbstractFileBrowserView.java +++ b/app/src/main/java/muon/screens/appwin/tabs/filebrowser/AbstractFileBrowserView.java @@ -58,7 +58,7 @@ public AbstractFileBrowserView(FileBrowserViewParent parent) { this.add(contentPanel, Integer.valueOf(1)); this.add(inputBlockerPanel, Integer.valueOf(2)); - setBackground(AppTheme.INSTANCE.getBackground()); + //setBackground(AppTheme.INSTANCE.getBackground()); installMouseListener(table); this.addComponentListener(new ComponentAdapter() { @@ -98,108 +98,124 @@ protected InputBlockerPanel getInputBlockerPanel() { return inputBlockerPanel; } - private void createContentPanel() { - var c1 = AppTheme.INSTANCE.getBackground(); - var toolbar = Box.createHorizontalBox(); - toolbar.setOpaque(true); - toolbar.setBackground(c1); + private JToolBar createToolbar() { + var toolbar = new JToolBar(); + toolbar.setBackground(UIManager.getColor("TextArea.background")); - btnBack = AppUtils.createIconButton(IconCode.RI_ARROW_LEFT_LINE); + btnBack =new JButton(AppUtils.createSVGIcon("arrow_back_black_24dp.svg", 20, Color.GRAY)); // AppUtils.createIconToolbarButton(IconCode.RI_ARROW_LEFT_LINE); btnBack.addActionListener(e -> onBack()); - btnBack.setForeground(AppTheme.INSTANCE.getDarkForeground()); - btnForward = AppUtils.createIconButton(IconCode.RI_ARROW_RIGHT_LINE); + //btnBack.setForeground(AppTheme.INSTANCE.getDarkForeground()); + btnForward =new JButton(AppUtils.createSVGIcon("arrow_forward_black_24dp.svg", 20, Color.GRAY)); // AppUtils.createIconToolbarButton(IconCode.RI_ARROW_RIGHT_LINE); btnForward.addActionListener(e -> onNext()); - btnForward.setForeground(AppTheme.INSTANCE.getDarkForeground()); - btnUp = AppUtils.createIconButton(IconCode.RI_ARROW_UP_LINE); + //btnForward.setForeground(AppTheme.INSTANCE.getDarkForeground()); + btnUp = new JButton(AppUtils.createSVGIcon("arrow_upward_black_24dp.svg", 20, Color.GRAY)); // AppUtils.createIconToolbarButton(IconCode.RI_ARROW_UP_LINE); btnUp.addActionListener(e -> onUp()); - btnUp.setForeground(AppTheme.INSTANCE.getDarkForeground()); - btnHome = AppUtils.createIconButton(IconCode.RI_HOME_4_LINE); - btnHome.setForeground(AppTheme.INSTANCE.getDarkForeground()); + //btnUp.setForeground(AppTheme.INSTANCE.getDarkForeground()); + btnHome = new JButton(AppUtils.createSVGIcon("home_black_24dp.svg", 20, Color.GRAY)); // AppUtils.createIconToolbarButton(IconCode.RI_HOME_4_LINE); + //btnHome.setForeground(AppTheme.INSTANCE.getDarkForeground()); btnHome.addActionListener(e -> navigate(null)); - toolbar.add(Box.createRigidArea(new Dimension(5, 30))); + //toolbar.add(Box.createRigidArea(new Dimension(5, 30))); toolbar.add(btnBack); - toolbar.add(Box.createRigidArea(new Dimension(5, 30))); + //toolbar.add(Box.createRigidArea(new Dimension(5, 30))); toolbar.add(btnForward); - toolbar.add(Box.createRigidArea(new Dimension(5, 30))); + //toolbar.add(Box.createRigidArea(new Dimension(5, 30))); toolbar.add(btnUp); - toolbar.add(Box.createRigidArea(new Dimension(5, 30))); + //toolbar.add(Box.createRigidArea(new Dimension(5, 30))); toolbar.add(btnHome); - toolbar.add(Box.createRigidArea(new Dimension(5, 30))); + //toolbar.add(Box.createRigidArea(new Dimension(5, 30))); txtAddress = new JTextField(); txtAddress.putClientProperty("textField.noBorder", Boolean.TRUE); - txtAddress.setBackground(c1); - txtAddress.setForeground(AppTheme.INSTANCE.getForeground()); + //txtAddress.setBackground(c1); + //txtAddress.setForeground(AppTheme.INSTANCE.getForeground()); txtAddress.setBorder(new EmptyBorder(0, 5, 0, 0)); txtAddress.setText(""); txtAddress.addActionListener(e -> { navigate(txtAddress.getText()); }); toolbar.add(txtAddress); - btnSearch = AppUtils.createIconButton(IconCode.RI_SEARCH_LINE); - btnSearch.setForeground(AppTheme.INSTANCE.getDarkForeground()); - toolbar.add(btnSearch); - toolbar.add(Box.createRigidArea(new Dimension(6, 30))); - btnRefresh = AppUtils.createIconButton(IconCode.RI_REFRESH_LINE); + btnRefresh = new JButton(AppUtils.createSVGIcon("autorenew_black_24dp.svg", 20, Color.GRAY));// AppUtils.createIconToolbarButton(IconCode.RI_REFRESH_LINE); btnRefresh.addActionListener(e -> onRefresh()); - btnRefresh.setForeground(AppTheme.INSTANCE.getDarkForeground()); + //btnRefresh.setForeground(AppTheme.INSTANCE.getDarkForeground()); toolbar.add(btnRefresh); - toolbar.add(Box.createRigidArea(new Dimension(3, 30))); - toolbar.add(AppUtils.createIconButton(IconCode.RI_MORE_2_LINE)); - toolbar.add(Box.createRigidArea(new Dimension(5, 30))); - toolbar.setBorder(new EmptyBorder(2, 5, 0, 0)); + //toolbar.add(Box.createRigidArea(new Dimension(3, 30))); + + btnSearch = new JButton(AppUtils.createSVGIcon("search_black_24dp.svg", 20, Color.GRAY));// AppUtils.createIconToolbarButton(IconCode.RI_SEARCH_LINE); + //btnSearch.setForeground(AppTheme.INSTANCE.getDarkForeground()); + toolbar.add(btnSearch); + //toolbar.add(Box.createRigidArea(new Dimension(6, 30))); + + var btnMenu = new JButton(AppUtils.createSVGIcon("more_vert_black_24dp.svg", 20, Color.GRAY)); + toolbar.add(btnMenu); + //toolbar.add(Box.createRigidArea(new Dimension(5, 30))); + toolbar.setBorder(new CompoundBorder( + new MatteBorder(0, 0, 1, 0, UIManager.getColor("TableHeader.bottomSeparatorColor")), + toolbar.getBorder())); + //System.out.println(toolbar.getBorder()); + //toolbar.setBorder(new EmptyBorder(2, 5, 0, 0)); + System.out.println(UIManager.get("Component.borderColor")); + System.out.println(UIManager.get("TableHeader.bottomSeparatorColor")); + return toolbar; + } + + private void createContentPanel() { + //UIManager.put("TableHeader.showTrailingVerticalLine", true); + //var c1 = AppTheme.INSTANCE.getBackground(); + var toolbar = createToolbar(); folderViewTableModel = new FolderViewTableModel(true); table = new JTable(folderViewTableModel); table.setIntercellSpacing(new Dimension(0, 0)); - table.setBackground(c1); - table.setForeground(AppTheme.INSTANCE.getForeground()); + //table.setBackground(c1); + //table.setForeground(AppTheme.INSTANCE.getForeground()); table.setFillsViewportHeight(true); table.setShowGrid(false); table.setShowVerticalLines(false); table.setShowHorizontalLines(false); table.setDragEnabled(true); table.setDropMode(DropMode.ON); - var header = table.getTableHeader(); - header.setBackground(c1); - header.setBorder(new EmptyBorder(0, 0, 0, 0)); - header.setDefaultRenderer((a, b, c, d, e, f) -> { - var label = new JLabel(b.toString()); - label.setBorder( - new CompoundBorder(new EmptyBorder(0, 0, 5, 0), - new CompoundBorder( - new MatteBorder(1, f == 0 ? 0 : 1, 1, 0, AppTheme.INSTANCE.getButtonBorderColor()), - new EmptyBorder(5, 10, 5, 10) - ))); - label.setOpaque(true); - label.setBackground(c1); - label.setForeground(AppTheme.INSTANCE.getDarkForeground()); - label.setFont(new Font(Font.DIALOG, Font.PLAIN, 12)); - return label; - }); - table.setRowHeight(30); + //var header = table.getTableHeader(); + //header.setBackground(c1); + //header.setBorder(new EmptyBorder(0, 0, 0, 0)); +// header.setDefaultRenderer((a, b, c, d, e, f) -> { +// var label = new JLabel(b.toString()); +// label.setBorder( +// new CompoundBorder(new EmptyBorder(0, 0, 0, 0), +// new CompoundBorder( +// new MatteBorder(1, f == 0 ? 0 : 1, 1, 0, AppTheme.INSTANCE.getButtonBorderColor()), +// new EmptyBorder(5, 10, 5, 10) +// ))); +// label.setOpaque(true); +// label.setBackground(c1); +// label.setForeground(AppTheme.INSTANCE.getDarkForeground()); +// label.setFont(new Font(Font.DIALOG, Font.PLAIN, 12)); +// return label; +// }); + var renderer = new FolderViewTableCellRenderer( + UIManager.getColor("Table.background"), + UIManager.getColor("Table.selectionBackground"), + AppTheme.INSTANCE.getListIconColor(), + UIManager.getColor("Table.selectionForeground"), + UIManager.getColor("Table.foreground")); + //table.setRowHeight(30); + table.setRowHeight(renderer.calculateRowHeight()); table.setDefaultRenderer(Object.class, - new FolderViewTableCellRenderer( - c1, - AppTheme.INSTANCE.getListSelectionColor(), - AppTheme.INSTANCE.getListIconColor(), - AppTheme.INSTANCE.getSelectionForeground(), - AppTheme.INSTANCE.getForeground())); + renderer); table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); table.setComponentPopupMenu(this.popup); JScrollPane sp = new JScrollPane(table); - sp.setCorner(JScrollPane.UPPER_RIGHT_CORNER, createCorner(c1)); - sp.setBackground(c1); - sp.getViewport().setBackground(c1); + //sp.setCorner(JScrollPane.UPPER_RIGHT_CORNER, createCorner(table.getTableHeader().getBackground())); + //sp.setBackground(c1); + //sp.getViewport().setBackground(c1); sp.setViewportBorder(new EmptyBorder(0, 0, 0, 0)); - sp.setBorder(new EmptyBorder(0, 0, 5, 0)); + sp.setBorder(new EmptyBorder(0, 0, 0, 0)); resizeColumnWidth(table); contentPanel = new JPanel(new BorderLayout()); - contentPanel.setBackground(c1); + //contentPanel.setBackground(c1); contentPanel.add(sp); contentPanel.add(toolbar, BorderLayout.NORTH); } diff --git a/app/src/main/java/muon/screens/appwin/tabs/filebrowser/DualPaneFileBrowser.java b/app/src/main/java/muon/screens/appwin/tabs/filebrowser/DualPaneFileBrowser.java index 9ca6a379..defaf986 100644 --- a/app/src/main/java/muon/screens/appwin/tabs/filebrowser/DualPaneFileBrowser.java +++ b/app/src/main/java/muon/screens/appwin/tabs/filebrowser/DualPaneFileBrowser.java @@ -1,15 +1,18 @@ package muon.screens.appwin.tabs.filebrowser; +import com.formdev.flatlaf.extras.FlatSVGIcon; import muon.constants.Orientation; import muon.dto.file.FileInfo; import muon.screens.appwin.AppWin; import muon.screens.appwin.tabs.filebrowser.local.LocalFileBrowserView; import muon.screens.appwin.tabs.filebrowser.sftp.SftpFileBrowserView; import muon.screens.appwin.tabs.filebrowser.transfer.foreground.ForegroundTransferProgressPanel; +import muon.screens.appwin.tabs.filebrowser.transfer.foreground.TransferDialog; import muon.screens.sessionmgr.SessionManager; import muon.service.SftpSession; import muon.service.SftpUploadTask; import muon.styles.AppTheme; +import muon.styles.FontIcon; import muon.util.AppUtils; import muon.util.IconCode; import muon.widgets.SplitPanel; @@ -20,12 +23,14 @@ import javax.swing.*; import java.awt.*; import java.awt.event.ActionListener; +import java.io.IOException; import java.util.List; +import java.util.function.IntConsumer; public class DualPaneFileBrowser extends JPanel implements FileBrowserViewParent { private SplitPanel splitPane; - private TabbedPanel leftTabs; - private TabbedPanel rightTabs; + private JTabbedPane leftTabs; + private JTabbedPane rightTabs; private JPanel leftTabHolder, rightTabHolder; private AppWin appWin; private ForegroundTransferProgressPanel transferPanel; @@ -84,21 +89,38 @@ private JPopupMenu createPopupMenu(ActionListener actLocal, ActionListener actRe return popupMenu; } - private void createLocalTab(TabbedPanel tabbedPanel) { + private void createLocalTab(JTabbedPane tabbedPanel) { var localFileBrowser = new LocalFileBrowserView(this); - tabbedPanel.addTab("Local", IconCode.RI_HARD_DRIVE_3_LINE, + FlatSVGIcon icon = null; + try { + icon = new FlatSVGIcon(getClass().getResourceAsStream("/icons/folder-fill.svg")); + //icon.derive(24,24) + } catch (IOException e) { + throw new RuntimeException(e); + } +// icon.setColorFilter(FlatSVGIcon.ColorFilter.getInstance() +// .add( Color.black, null, Color.white ) +// .add( Color.white, null, Color.black )); + tabbedPanel.addTab("Local", //new FontIcon(IconCode.RI_HARD_DRIVE_3_LINE,16,16,16,AppTheme.INSTANCE.getSelectionColor()) + AppUtils.createSVGIcon("laptop_black_24dp.svg", 18, Color.GRAY), + //icon.derive(16,16), localFileBrowser); +// tabbedPanel.addTab("Local", IconCode.RI_HARD_DRIVE_3_LINE, +// localFileBrowser); showTab(tabbedPanel); localFileBrowser.init(); } - private void createRemoteTab(TabbedPanel tabbedPanel) { + private void createRemoteTab(JTabbedPane tabbedPanel) { var window = SwingUtilities.windowForComponent(this); var sessionInfo = SessionManager.showDialog(window); if (sessionInfo != null) { var sftpFileBrowser = new SftpFileBrowserView(sessionInfo, this); - tabbedPanel.addTab(sessionInfo.getName(), IconCode.RI_FLASH_LINE, + tabbedPanel.addTab(sessionInfo.getName(), + AppUtils.createSVGIcon("language_black_24dp.svg", 18, Color.GRAY), sftpFileBrowser); +// tabbedPanel.addTab(sessionInfo.getName(), IconCode.RI_FLASH_LINE, +// sftpFileBrowser); showTab(tabbedPanel); sftpFileBrowser.init(); } @@ -108,7 +130,7 @@ public void init() { createLocalTab(leftTabs); } - private void showTab(TabbedPanel tabbedPanel) { + private void showTab(JTabbedPane tabbedPanel) { if (this.leftTabs == tabbedPanel) { ((CardLayout) leftTabHolder.getLayout()).show(leftTabHolder, "TABS"); } @@ -117,58 +139,100 @@ private void showTab(TabbedPanel tabbedPanel) { } } - private TabbedPanel createTab(JPopupMenu popupMenu) { - var addTabComponent = AppUtils.createAddTabButton(); + private JTabbedPane createTab(JPopupMenu popupMenu) { + var tab = new JTabbedPane(); + tab.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); + tab.putClientProperty("JTabbedPane.tabClosable", true); + //tab.putClientProperty("JTabbedPane.showContentSeparator", false); + tab.putClientProperty("JTabbedPane.tabCloseCallback", (IntConsumer) tabIndex -> { + // close tab here + var c = tab.getComponentAt(tabIndex); + tab.removeTabAt(tabIndex); + if (c instanceof AbstractFileBrowserView) { + ((AbstractFileBrowserView) c).dispose(); + } + handleTabClosure(tab); + }); + + FlatSVGIcon.ColorFilter filter = new FlatSVGIcon.ColorFilter(); + filter.add(Color.BLACK, Color.GRAY); + FlatSVGIcon icon = null; + try { + icon = new FlatSVGIcon(getClass().getResourceAsStream("/icons/add-line.svg")); + } catch (IOException e) { + throw new RuntimeException(e); + } + icon.setColorFilter(filter); + var addTabComponent = new JButton(icon.derive(16, 16)); + addTabComponent.putClientProperty("button.popup", addTabComponent); + //addTabComponent.putClientProperty("JButton.buttonType", "toolBarButton"); addTabComponent.addActionListener(e -> { popupMenu.pack(); popupMenu.setInvoker(addTabComponent); popupMenu.show(addTabComponent, addTabComponent.getWidth() - popupMenu.getPreferredSize().width, addTabComponent.getHeight()); }); - var tabbedPanel = new TabbedPanel( - false, - false, - new Color(52, 117, 233), - AppTheme.INSTANCE.getDarkControlBackground(), - new Color(52, 117, 233), - AppTheme.INSTANCE.getDisabledForeground(), - AppTheme.INSTANCE.getBackground(), - AppTheme.INSTANCE.getDarkControlBackground(), - AppTheme.INSTANCE.getForeground(), - AppTheme.INSTANCE.getTitleForeground(), - IconCode.RI_CLOSE_LINE, - AppTheme.INSTANCE.getButtonBorderColor(), - addTabComponent, - false, - true, - false - ); - - tabbedPanel.addTabListener(new TabListener() { - @Override - public void selectionChanged(TabEvent e) { - } - - @Override - public boolean tabClosing(TabEvent e) { - return true; - } - - @Override - public void tabClosed(TabEvent e) { - var c = e.getTabContent(); - if (c instanceof AbstractFileBrowserView) { - ((AbstractFileBrowserView) c).dispose(); - } - handleTabClosure(tabbedPanel); - } - }); - - return tabbedPanel; + var toolbar = new JToolBar(); + toolbar.setFloatable(false); + toolbar.setBorder(null); + toolbar.add(Box.createHorizontalGlue()); + toolbar.add(addTabComponent); + tab.putClientProperty("JTabbedPane.trailingComponent", toolbar); + + return tab; +// +// var addTabComponent = AppUtils.createAddTabButton(); +// addTabComponent.putClientProperty("button.popup", addTabComponent); +// addTabComponent.addActionListener(e -> { +// popupMenu.pack(); +// popupMenu.setInvoker(addTabComponent); +// popupMenu.show(addTabComponent, addTabComponent.getWidth() - popupMenu.getPreferredSize().width, addTabComponent.getHeight()); +// }); +// +// var tabbedPanel = new TabbedPanel( +// false, +// false, +// new Color(52, 117, 233), +// AppTheme.INSTANCE.getDarkControlBackground(), +// new Color(52, 117, 233), +// AppTheme.INSTANCE.getDisabledForeground(), +// AppTheme.INSTANCE.getBackground(), +// AppTheme.INSTANCE.getDarkControlBackground(), +// AppTheme.INSTANCE.getForeground(), +// AppTheme.INSTANCE.getTitleForeground(), +// IconCode.RI_CLOSE_LINE, +// AppTheme.INSTANCE.getButtonBorderColor(), +// addTabComponent, +// false, +// true, +// false +// ); +// +// tabbedPanel.addTabListener(new TabListener() { +// @Override +// public void selectionChanged(TabEvent e) { +// } +// +// @Override +// public boolean tabClosing(TabEvent e) { +// return true; +// } +// +// @Override +// public void tabClosed(TabEvent e) { +// var c = e.getTabContent(); +// if (c instanceof AbstractFileBrowserView) { +// ((AbstractFileBrowserView) c).dispose(); +// } +// handleTabClosure(tabbedPanel); +// } +// }); +// +// return tabbedPanel; } - private void handleTabClosure(TabbedPanel tabbedPanel) { + private void handleTabClosure(JTabbedPane tabbedPanel) { if (tabbedPanel == leftTabs && tabbedPanel.getTabCount() == 0) { ((CardLayout) leftTabHolder.getLayout()).show(leftTabHolder, "HOME"); } @@ -183,8 +247,9 @@ public void beginSftpUpload( String remoteFolder, List remoteFiles, SftpSession sftp) { - ((CardLayout) this.getLayout()).show(this, "TransferPanel"); - transferPanel.setSftpUploadTask(new SftpUploadTask(sftp, localFolder, localFiles, remoteFolder, remoteFiles)); - transferPanel.showConfirm(); + var transferDialog = new TransferDialog( + new SftpUploadTask(sftp, localFolder, localFiles, remoteFolder, remoteFiles), e -> { + }, SwingUtilities.windowForComponent(this)); + transferDialog.setVisible(true); } } diff --git a/app/src/main/java/muon/screens/appwin/tabs/filebrowser/FolderViewTableCellRenderer.java b/app/src/main/java/muon/screens/appwin/tabs/filebrowser/FolderViewTableCellRenderer.java index 2f905ab0..52639b29 100644 --- a/app/src/main/java/muon/screens/appwin/tabs/filebrowser/FolderViewTableCellRenderer.java +++ b/app/src/main/java/muon/screens/appwin/tabs/filebrowser/FolderViewTableCellRenderer.java @@ -1,6 +1,8 @@ package muon.screens.appwin.tabs.filebrowser; +import com.formdev.flatlaf.extras.FlatSVGIcon; import muon.dto.file.FileInfo; +import muon.styles.AppTheme; import muon.util.AppUtils; import muon.util.IconCode; import muon.util.IconFont; @@ -9,12 +11,14 @@ import javax.swing.border.EmptyBorder; import javax.swing.table.TableCellRenderer; import java.awt.*; +import java.io.IOException; public class FolderViewTableCellRenderer implements TableCellRenderer { private JPanel p1; private JLabel iconLbl; private JLabel label1, label2; private Color background, selectionBackground, iconForeground, selectionForeground, foreground; + private ImageIcon folderIcon, fileIcon; public FolderViewTableCellRenderer(Color background, Color selectionBackground, @@ -29,9 +33,25 @@ public FolderViewTableCellRenderer(Color background, this.selectionForeground = selectionForeground; this.foreground = foreground; + FlatSVGIcon.ColorFilter filter = new FlatSVGIcon.ColorFilter(); + filter.add(Color.BLACK, AppTheme.INSTANCE.getListIconColor()); + try { + var icon1 = new FlatSVGIcon(getClass().getResourceAsStream("/icons/folder-fill.svg")); + icon1.setColorFilter(filter); + folderIcon = icon1.derive(24, 24); + + var icon2 = new FlatSVGIcon(getClass().getResourceAsStream("/icons/file-2-fill.svg")); + icon2.setColorFilter(filter); + fileIcon = icon2.derive(24, 24); + } catch (IOException e) { + throw new RuntimeException(e); + } + iconLbl = createIconLabel(); label1 = createTextLabel(); + label1.setBorder(new EmptyBorder(5, 7, 5, 10)); label2 = createTextLabel(); + label2.setBorder(new EmptyBorder(5, 10, 5, 10)); label2.setOpaque(true); p1.add(iconLbl, BorderLayout.WEST); @@ -42,7 +62,7 @@ private JLabel createIconLabel() { var iconLbl = new JLabel(); iconLbl.setVerticalAlignment(JLabel.CENTER); iconLbl.setVerticalTextPosition(JLabel.CENTER); - iconLbl.setBorder(new EmptyBorder(0, 10, 0, 0)); + iconLbl.setBorder(new EmptyBorder(4, 10, 4, 0)); iconLbl.setFont(IconFont.getSharedInstance().getIconFont(24.0f)); iconLbl.setForeground(iconForeground); return iconLbl; @@ -65,9 +85,9 @@ public Component getTableCellRendererComponent(JTable table, var fileInfo = (FileInfo) value; var col = table.convertColumnIndexToModel(column); if (col == 0) { - iconLbl.setText(fileInfo.isDirectory() - ? IconCode.RI_FOLDER_FILL.getValue() - : IconCode.RI_FILE_FILL.getValue()); + iconLbl.setIcon(fileInfo.isDirectory() + ? folderIcon + : fileIcon); label1.setText(fileInfo.getName()); p1.setBackground(isSelected ? selectionBackground : background); label1.setForeground(isSelected ? selectionForeground : foreground); @@ -98,4 +118,10 @@ public Component getTableCellRendererComponent(JTable table, return label2; } } + + public int calculateRowHeight() { + iconLbl.setIcon(folderIcon); + label1.setText("some text"); + return p1.getPreferredSize().height; + } } diff --git a/app/src/main/java/muon/screens/appwin/tabs/filebrowser/transfer/foreground/FileListRenderer.java b/app/src/main/java/muon/screens/appwin/tabs/filebrowser/transfer/foreground/FileListRenderer.java index c9d1e3dd..ce72859b 100644 --- a/app/src/main/java/muon/screens/appwin/tabs/filebrowser/transfer/foreground/FileListRenderer.java +++ b/app/src/main/java/muon/screens/appwin/tabs/filebrowser/transfer/foreground/FileListRenderer.java @@ -2,6 +2,7 @@ import muon.dto.file.FileInfo; import muon.styles.AppTheme; +import muon.util.AppUtils; import muon.util.IconCode; import muon.util.IconFont; @@ -9,40 +10,23 @@ import javax.swing.border.EmptyBorder; import java.awt.*; -public class FileListRenderer implements ListCellRenderer { - private JPanel panel1, panel2; - private JLabel lblIcon, lblText, lblInfo; +public class FileListRenderer extends JLabel implements ListCellRenderer { + private Icon icoFile, icoFolder; public FileListRenderer() { - panel1 = new JPanel(new BorderLayout(5, 10)); - panel1.setBorder(new EmptyBorder(0, 0, 5, 0)); - lblIcon = new JLabel(); - lblIcon.setForeground(AppTheme.INSTANCE.getDarkForeground()); - lblIcon.setFont(IconFont.getSharedInstance().getIconFont(32.0f)); - - lblText = new JLabel(); - lblText.setFont(new Font(Font.DIALOG, Font.PLAIN, 12)); - lblText.setForeground(AppTheme.INSTANCE.getForeground()); - - lblInfo = new JLabel(); - lblInfo.setFont(new Font(Font.DIALOG, Font.PLAIN, 11)); - lblInfo.setForeground(AppTheme.INSTANCE.getDarkForeground()); - - panel2 = new JPanel(new BorderLayout(5, 0)); - - panel2.add(lblText, BorderLayout.NORTH); - panel2.add(lblInfo); - - panel1.add(lblIcon, BorderLayout.WEST); - panel1.add(panel2); - + icoFile = AppUtils.createSVGIcon("file-2-fill.svg", 16, AppTheme.INSTANCE.getListIconColor()); + icoFolder = AppUtils.createSVGIcon("folder-fill.svg", 16, AppTheme.INSTANCE.getListIconColor()); + setIcon(icoFolder); + setText("Sample text"); + setBorder(new EmptyBorder(5, 5, 5, 5)); + setOpaque(true); } @Override public Component getListCellRendererComponent(JList list, FileInfo value, int index, boolean isSelected, boolean cellHasFocus) { - lblIcon.setText(value.isDirectory() ? IconCode.RI_FOLDER_FILL.getValue() : IconCode.RI_FILE_FILL.getValue()); - lblText.setText(value.getName()); - lblInfo.setText(value.isDirectory() ? "Folder" : value.getSize() + ""); - return panel1; + setIcon(value.isDirectory() ? icoFolder : icoFile); + setText(value.getName()); + setBackground(isSelected ? list.getSelectionBackground() : list.getBackground()); + return this; } } diff --git a/app/src/main/java/muon/screens/appwin/tabs/filebrowser/transfer/foreground/ForegroundTransferProgressPanel.java b/app/src/main/java/muon/screens/appwin/tabs/filebrowser/transfer/foreground/ForegroundTransferProgressPanel.java index 9e53701a..238f1e83 100644 --- a/app/src/main/java/muon/screens/appwin/tabs/filebrowser/transfer/foreground/ForegroundTransferProgressPanel.java +++ b/app/src/main/java/muon/screens/appwin/tabs/filebrowser/transfer/foreground/ForegroundTransferProgressPanel.java @@ -112,7 +112,7 @@ private void transfer() { try { if (!sftpUploadTask.isConnected()) { SwingUtilities.invokeAndWait(inputBlockerPanel::blockInput); - sftpUploadTask.connect(inputBlockerPanel); + //sftpUploadTask.connect(inputBlockerPanel); SwingUtilities.invokeAndWait(inputBlockerPanel::unblockInput); } SwingUtilities.invokeAndWait(this::showProgress); diff --git a/app/src/main/java/muon/screens/appwin/tabs/filebrowser/transfer/foreground/TransferConfirmPanel.java b/app/src/main/java/muon/screens/appwin/tabs/filebrowser/transfer/foreground/TransferConfirmPanel.java index 7d3b86bc..eb0344ba 100644 --- a/app/src/main/java/muon/screens/appwin/tabs/filebrowser/transfer/foreground/TransferConfirmPanel.java +++ b/app/src/main/java/muon/screens/appwin/tabs/filebrowser/transfer/foreground/TransferConfirmPanel.java @@ -14,15 +14,15 @@ public class TransferConfirmPanel extends JPanel { private JTextField txtPath; private JLabel lblFileDetails, lblFileConflict, lblConflictAction; private JList conflictingFiles; + private JScrollPane scrollPane; private DefaultListModel conflictingFilesModel; private JCheckBox chkBackground; private JComboBox cmbConflict; private JButton btnOK, btnCancel; public TransferConfirmPanel(ActionListener onOK, ActionListener onCancel) { - super(new GridBagLayout()); - - var vbox = Box.createVerticalBox(); + setLayout(new BorderLayout()); + setBorder(new EmptyBorder(10, 10, 10, 10)); lblFileDetails = new JLabel("Transfer 5 files and 2 folders to"); lblFileDetails.setBorder(new EmptyBorder(5, 0, 5, 0)); @@ -36,7 +36,7 @@ public TransferConfirmPanel(ActionListener onOK, ActionListener onCancel) { cmbConflict = new JComboBox<>(new String[]{"Replace if newer", "Replace", "Auto rename", "Skip"}); cmbConflict.setFont(new Font(Font.DIALOG, Font.PLAIN, 12)); lblConflictAction = new JLabel("What to do"); - lblConflictAction.setBorder(new EmptyBorder(15, 0, 0, 0)); + lblConflictAction.setBorder(new EmptyBorder(10, 0, 0, 0)); btnOK = new JButton("OK"); btnCancel = new JButton("Cancel"); btnOK.addActionListener(onOK); @@ -51,37 +51,22 @@ public TransferConfirmPanel(ActionListener onOK, ActionListener onCancel) { lblFileConflict = new JLabel("Following files already exist"); lblFileConflict.setAlignmentX(Component.LEFT_ALIGNMENT); - lblFileConflict.setBorder(new EmptyBorder(10, 0, 10, 0)); - - conflictingFiles.setSelectionBackground(AppTheme.INSTANCE.getBackground()); + lblFileConflict.setBorder(new EmptyBorder(10, 0, 5, 0)); conflictingFiles.setCellRenderer(new FileListRenderer()); - var listScrollPane = new JScrollPane(conflictingFiles); - listScrollPane.getViewport().setBackground(AppTheme.INSTANCE.getBackground()); - listScrollPane.setBackground(AppTheme.INSTANCE.getBackground()); - listScrollPane.setForeground(AppTheme.INSTANCE.getForeground()); - listScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - listScrollPane.setAlignmentX(Component.LEFT_ALIGNMENT); + scrollPane = new JScrollPane(conflictingFiles); + scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + scrollPane.setAlignmentX(Component.LEFT_ALIGNMENT); var dim = new Dimension(txtPath.getPreferredSize().width, 100); - listScrollPane.setPreferredSize(dim); + scrollPane.setPreferredSize(dim); - vbox.add(lblFileDetails); - vbox.add(txtPath); - vbox.add(lblFileConflict); - vbox.add(listScrollPane); + var vbox1 = Box.createVerticalBox(); + vbox1.add(lblFileDetails); + vbox1.add(txtPath); + vbox1.add(lblFileConflict); - vbox.add(lblConflictAction); - //vbox.add(cmbConflict); - -// var hb1 = Box.createHorizontalBox(); -// hb1.setBorder(new EmptyBorder(10, 0, 5, 0)); -// hb1.add(lblConflictAction); -// hb1.add(Box.createHorizontalGlue()); -// hb1.add(cmbConflict); -// hb1.setAlignmentX(Component.LEFT_ALIGNMENT); -// -// vbox.add(hb1); - //chkBackground.setBorder(new EmptyBorder(20,0,10,0)); - //vbox.add(chkBackground); + var vbox2 = Box.createVerticalBox(); + vbox2.add(scrollPane); + vbox2.add(lblConflictAction); var hb2 = Box.createHorizontalBox(); hb2.setBorder(new EmptyBorder(5, 0, 5, 0)); @@ -92,11 +77,9 @@ public TransferConfirmPanel(ActionListener onOK, ActionListener onCancel) { hb2.add(btnCancel); hb2.setAlignmentX(Component.LEFT_ALIGNMENT); - vbox.add(hb2); - - var c = 0; - var gc = new GridBagConstraints(); - add(vbox, gc); + add(vbox1, BorderLayout.NORTH); + add(vbox2); + add(hb2, BorderLayout.SOUTH); } public void setFileInfo(String info, String path, List files) { @@ -107,6 +90,7 @@ public void setFileInfo(String info, String path, List files) { lblFileConflict.setVisible(files.size() > 0); cmbConflict.setVisible(files.size() > 0); lblConflictAction.setVisible(files.size() > 0); + scrollPane.setVisible(files.size() > 0); } public void setFocus() { diff --git a/app/src/main/java/muon/screens/appwin/tabs/filebrowser/transfer/foreground/TransferDialog.java b/app/src/main/java/muon/screens/appwin/tabs/filebrowser/transfer/foreground/TransferDialog.java new file mode 100644 index 00000000..93a083de --- /dev/null +++ b/app/src/main/java/muon/screens/appwin/tabs/filebrowser/transfer/foreground/TransferDialog.java @@ -0,0 +1,103 @@ +package muon.screens.appwin.tabs.filebrowser.transfer.foreground; + +import muon.dto.file.FileInfo; +import muon.service.SftpUploadTask; +import muon.util.AppUtils; + +import javax.swing.*; +import java.awt.*; +import java.util.ArrayList; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +public class TransferDialog extends JDialog { + private TransferConfirmPanel transferConfirmPanel; + private TransferProgressPanel transferProgressPanel; + private TransferRetryPanel transferRetryPanel; + private Consumer result; + private SftpUploadTask sftpUploadTask; + + public TransferDialog(SftpUploadTask sftpUploadTask, Consumer result, Window window) { + super(window); + this.result = result; + setModal(true); + setTitle("File transfer"); + setSize(420, 300); + setLocationRelativeTo(getOwner()); + getContentPane().setLayout(new CardLayout()); + createUI(); + setSftpUploadTask(sftpUploadTask); + showConfirm(); + } + + private void setSftpUploadTask(SftpUploadTask sftpUploadTask) { + this.sftpUploadTask = sftpUploadTask; + this.transferProgressPanel.setProgress(0); + var folderCount = this.sftpUploadTask.getLocalFiles().stream().filter(FileInfo::isDirectory).count(); + var fileCount = this.sftpUploadTask.getLocalFiles().size() - folderCount; + var texts = new ArrayList(); + texts.add("Transfer"); + if (folderCount > 0) { + texts.add(folderCount + " folder" + (folderCount > 1 ? "s" : "")); + } + if (fileCount > 0) { + if (folderCount > 0) { + texts.add("and"); + } + texts.add(fileCount + " file" + (fileCount > 1 ? "s" : "")); + } + var remoteFileNames = sftpUploadTask.getRemoteFiles().stream().map(FileInfo::getName).collect(Collectors.toSet()); + var conflictingFiles = sftpUploadTask.getLocalFiles().stream().filter( + f -> remoteFileNames.contains(f.getName())).toList(); + this.transferConfirmPanel.setFileInfo(String.format(String.join(" ", texts)), + this.sftpUploadTask.getRemoteFolder(), conflictingFiles); + } + + private void showConfirm() { + ((CardLayout) getContentPane().getLayout()).show(getContentPane(), "TransferConfirmPanel"); + transferConfirmPanel.setFocus(); + } + + private void showProgress() { + ((CardLayout) getContentPane().getLayout()).show(getContentPane(), "TransferProgressPanel"); + setSize(320, 200); + setLocationRelativeTo(getOwner()); + } + + private void showError() { + ((CardLayout) getContentPane().getLayout()).show(getContentPane(), "TransferRetryPanel"); + setSize(320, 300); + setLocationRelativeTo(getOwner()); + } + + private void transfer() { + AppUtils.runAsync(() -> { + try { + if (!sftpUploadTask.isConnected()) { + sftpUploadTask.connect(); + } + SwingUtilities.invokeAndWait(this::showProgress); + sftpUploadTask.start(prg -> { + SwingUtilities.invokeLater(() -> { + transferProgressPanel.setProgress(prg); + }); + }); + result.accept(true); + } catch (Exception ex) { + ex.printStackTrace(); + showError(); + } + }); + } + + private void createUI() { + transferConfirmPanel = new TransferConfirmPanel(e -> transfer(), e -> result.accept(false)); + transferRetryPanel = new TransferRetryPanel(null, null); + transferProgressPanel = new TransferProgressPanel(null); + getContentPane().add(transferConfirmPanel, "TransferConfirmPanel"); + getContentPane().add(transferProgressPanel, "TransferProgressPanel"); + getContentPane().add(transferRetryPanel, "TransferRetryPanel"); + } + + +} diff --git a/app/src/main/java/muon/screens/appwin/tabs/filebrowser/transfer/foreground/TransferProgressPanel.java b/app/src/main/java/muon/screens/appwin/tabs/filebrowser/transfer/foreground/TransferProgressPanel.java index 12bf039f..40485f6d 100644 --- a/app/src/main/java/muon/screens/appwin/tabs/filebrowser/transfer/foreground/TransferProgressPanel.java +++ b/app/src/main/java/muon/screens/appwin/tabs/filebrowser/transfer/foreground/TransferProgressPanel.java @@ -13,10 +13,11 @@ public class TransferProgressPanel extends JPanel { private JButton btnCancel; public TransferProgressPanel(ActionListener onCancel) { - super(new GridBagLayout()); - lblFileDetails = new JLabel("Transferring abc.txt"); + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + setBorder(new EmptyBorder(10, 10, 10, 10)); + lblFileDetails = new JLabel("Transferring 5 files to"); lblFileDetails.setAlignmentX(Component.LEFT_ALIGNMENT); - lblFileDetails.setBorder(new EmptyBorder(0, 0, 10, 0)); + lblFileDetails.setBorder(new EmptyBorder(10, 0, 10, 0)); prgTransfer = new JProgressBar(); prgTransfer.setAlignmentX(Component.LEFT_ALIGNMENT); prgTransfer.setPreferredSize(new Dimension(300, 5)); @@ -29,16 +30,13 @@ public TransferProgressPanel(ActionListener onCancel) { var hb1 = Box.createHorizontalBox(); hb1.setAlignmentX(Component.LEFT_ALIGNMENT); hb1.add(Box.createHorizontalGlue()); - hb1.add(Box.createRigidArea(new Dimension(10, 10))); hb1.add(btnCancel); - var vbox = Box.createVerticalBox(); - vbox.add(lblFileDetails); - vbox.add(prgTransfer); - vbox.add(lblProgressInfo); - vbox.add(hb1); - - add(vbox); + this.add(lblFileDetails); + this.add(prgTransfer); + this.add(lblProgressInfo); + this.add(Box.createVerticalGlue()); + this.add(hb1); } public void setProgress(int progress) { diff --git a/app/src/main/java/muon/screens/appwin/tabs/filebrowser/transfer/foreground/TransferRetryPanel.java b/app/src/main/java/muon/screens/appwin/tabs/filebrowser/transfer/foreground/TransferRetryPanel.java index 5cb4c1d6..f8bcad98 100644 --- a/app/src/main/java/muon/screens/appwin/tabs/filebrowser/transfer/foreground/TransferRetryPanel.java +++ b/app/src/main/java/muon/screens/appwin/tabs/filebrowser/transfer/foreground/TransferRetryPanel.java @@ -14,9 +14,7 @@ public class TransferRetryPanel extends JPanel { private JLabel lblErrorDetails; public TransferRetryPanel(ActionListener retryAction, ActionListener cancelAction) { - super(new GridBagLayout()); - - var vbox = Box.createVerticalBox(); + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); var lblIcon = new JLabel(); lblIcon.setFont(IconFont.getSharedInstance().getIconFont(128.0f)); @@ -39,12 +37,13 @@ public TransferRetryPanel(ActionListener retryAction, ActionListener cancelActio hb2.add(btnRetry); hb2.add(Box.createRigidArea(new Dimension(10, 10))); hb2.add(btnCancel); + hb2.add(Box.createHorizontalGlue()); hb2.setAlignmentX(Component.CENTER_ALIGNMENT); - vbox.add(lblIcon); - vbox.add(lblErrorDetails); - vbox.add(hb2); - - add(vbox); + this.add(Box.createVerticalGlue()); + this.add(lblIcon); + this.add(lblErrorDetails); + this.add(hb2); + hb2.add(Box.createVerticalGlue()); } } diff --git a/app/src/main/java/muon/screens/appwin/tabs/terminal/CustomizedSettingsProvider.java b/app/src/main/java/muon/screens/appwin/tabs/terminal/CustomizedSettingsProvider.java index b187872f..81162eb1 100644 --- a/app/src/main/java/muon/screens/appwin/tabs/terminal/CustomizedSettingsProvider.java +++ b/app/src/main/java/muon/screens/appwin/tabs/terminal/CustomizedSettingsProvider.java @@ -56,8 +56,8 @@ public final TerminalColor getTerminalColor(int rgb) { @Override public TextStyle getDefaultStyle() { - return new TextStyle(getTerminalColor(AppTheme.INSTANCE.getForeground().getRGB()), - getTerminalColor(AppTheme.INSTANCE.getBackground().getRGB())); + return new TextStyle(getTerminalColor(UIManager.getColor("TextArea.foreground").getRGB()), + getTerminalColor(UIManager.getColor("TabbedPane.background").getRGB())); // return terminalTheme.getDefaultStyle(); } // diff --git a/app/src/main/java/muon/screens/appwin/tabs/terminal/TabbedTerminal.java b/app/src/main/java/muon/screens/appwin/tabs/terminal/TabbedTerminal.java index 24a856b8..1f3cf3e4 100644 --- a/app/src/main/java/muon/screens/appwin/tabs/terminal/TabbedTerminal.java +++ b/app/src/main/java/muon/screens/appwin/tabs/terminal/TabbedTerminal.java @@ -1,6 +1,7 @@ package muon.screens.appwin.tabs.terminal; import muon.App; +import muon.screens.appwin.tabs.filebrowser.AbstractFileBrowserView; import muon.screens.sessionmgr.SessionManager; import muon.styles.AppTheme; import muon.util.*; @@ -9,9 +10,10 @@ import javax.swing.*; import javax.swing.border.EmptyBorder; import java.awt.*; +import java.util.function.IntConsumer; public class TabbedTerminal extends JPanel { - private TabbedPanel leftTabs; + private JTabbedPane leftTabs; public TabbedTerminal() { super(new CardLayout()); @@ -21,63 +23,90 @@ public TabbedTerminal() { this.add(leftTabs, "TABS"); } - private TabbedPanel createTab() { - var addTabComponent = AppUtils.createAddTabButton(); - addTabComponent.setBorder(new EmptyBorder(2, 2, 2, 0)); + private JTabbedPane createTab() { + var addTabComponent = new JButton(AppUtils.createSVGIcon("add-line.svg", 16, Color.GRAY));// AppUtils.createAddTabButton(); + //addTabComponent.setBorder(new EmptyBorder(2, 2, 2, 0)); addTabComponent.putClientProperty("button.popup", addTabComponent); addTabComponent.addActionListener(e -> { openTab(); }); - var moreComponent = AppUtils.createMoreButton(); + var moreComponent = new JButton(AppUtils.createSVGIcon("more_vert_black_24dp.svg", 16, Color.GRAY));//AppUtils.createMoreButton(); - var b1 = Box.createHorizontalBox(); - b1.add(addTabComponent); - b1.add(moreComponent); +// var b1 = Box.createHorizontalBox(); +// b1.add(addTabComponent); +// b1.add(moreComponent); - var tabbedPanel = new TabbedPanel( - false, - false, - AppTheme.INSTANCE.getSelectionColor(), - AppTheme.INSTANCE.getDarkControlBackground(), - AppTheme.INSTANCE.getDarkForeground(), - AppTheme.INSTANCE.getDisabledForeground(), - AppTheme.INSTANCE.getBackground(), - AppTheme.INSTANCE.getDarkControlBackground(), - AppTheme.INSTANCE.getForeground(), - AppTheme.INSTANCE.getTitleForeground(), - IconCode.RI_CLOSE_LINE, - AppTheme.INSTANCE.getButtonBorderColor(), - b1, - false, - true, - false - ); - - tabbedPanel.addTabListener(new TabListener() { - @Override - public void selectionChanged(TabEvent e) { - } - - @Override - public boolean tabClosing(TabEvent e) { - return true; - } - - @Override - public void tabClosed(TabEvent e) { - var c = e.getTabContent(); - if (c instanceof TerminalContainer) { - ((TerminalContainer) c).dispose(); - } - handleTabClosure(tabbedPanel); + var tab = new JTabbedPane(); + System.out.println("aaaa: " + UIManager.getColor("TabbedPane.background")); + //tab.putClientProperty("JTabbedPane.background", UIManager.getColor("TextArea.background")); + //tab.putClientProperty("JTabbedPane.background", UIManager.getColor("TextArea.background")); + //tab.putClientProperty("JTabbedPane.showContentSeparator", false); + //tab.setBackground(UIManager.getColor("TextArea.background")); + tab.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); + tab.putClientProperty("JTabbedPane.tabClosable", true); + tab.putClientProperty("JTabbedPane.tabCloseCallback", (IntConsumer) tabIndex -> { + // close tab here + var c = tab.getComponentAt(tabIndex); + tab.removeTabAt(tabIndex); + if (c instanceof TerminalContainer) { + ((TerminalContainer) c).dispose(); } + handleTabClosure(tab); }); - return tabbedPanel; + var toolbar = new JToolBar(); + toolbar.setFloatable(false); + toolbar.setBorder(null); + toolbar.add(Box.createHorizontalGlue()); + toolbar.add(addTabComponent); + toolbar.add(moreComponent); + tab.putClientProperty("JTabbedPane.trailingComponent", toolbar); + return tab; + +// var tabbedPanel = new TabbedPanel( +// false, +// false, +// AppTheme.INSTANCE.getSelectionColor(), +// AppTheme.INSTANCE.getDarkControlBackground(), +// AppTheme.INSTANCE.getDarkForeground(), +// AppTheme.INSTANCE.getDisabledForeground(), +// AppTheme.INSTANCE.getBackground(), +// AppTheme.INSTANCE.getDarkControlBackground(), +// AppTheme.INSTANCE.getForeground(), +// AppTheme.INSTANCE.getTitleForeground(), +// IconCode.RI_CLOSE_LINE, +// AppTheme.INSTANCE.getButtonBorderColor(), +// b1, +// false, +// true, +// false +// ); +// +// tabbedPanel.addTabListener(new TabListener() { +// @Override +// public void selectionChanged(TabEvent e) { +// } +// +// @Override +// public boolean tabClosing(TabEvent e) { +// return true; +// } +// +// @Override +// public void tabClosed(TabEvent e) { +// var c = e.getTabContent(); +// if (c instanceof TerminalContainer) { +// ((TerminalContainer) c).dispose(); +// } +// handleTabClosure(tabbedPanel); +// } +// }); +// +// return tabbedPanel; } - private void handleTabClosure(TabbedPanel tabbedPanel) { + private void handleTabClosure(JTabbedPane tabbedPanel) { if (tabbedPanel == leftTabs && tabbedPanel.getTabCount() == 0) { ((CardLayout) this.getLayout()).show(this, "HOME"); } @@ -88,7 +117,8 @@ private void openTab() { var sessionInfo = SessionManager.showDialog(window); if (sessionInfo != null) { var terminal = new TerminalContainer(sessionInfo); - leftTabs.addTab(sessionInfo.getName(), IconCode.RI_TERMINAL_BOX_LINE, + leftTabs.addTab(sessionInfo.getName(), AppUtils.createSVGIcon("terminal-box-fill.svg", 18, Color.GRAY), + //IconCode.RI_TERMINAL_BOX_LINE, terminal); ((CardLayout) this.getLayout()).show(this, "TABS"); terminal.beginSession(); diff --git a/app/src/main/java/muon/screens/sessionmgr/SessionEditor.java b/app/src/main/java/muon/screens/sessionmgr/SessionEditor.java index b99926fb..be396aee 100644 --- a/app/src/main/java/muon/screens/sessionmgr/SessionEditor.java +++ b/app/src/main/java/muon/screens/sessionmgr/SessionEditor.java @@ -18,7 +18,7 @@ public class SessionEditor extends JPanel { private JLabel lblName; private JTextField txtName; - private TabbedPanel tabbedPanel; + private JTabbedPane tabbedPanel; private JButton btnConnect, btnCancel; private SshInfoPanel sshInfoPanel; private ActionListener connectAction, cancelAction; @@ -71,7 +71,7 @@ public int getHeaderHeight() { } private void createUI() { - this.setBackground(AppTheme.INSTANCE.getBackground()); + //this.setBackground(AppTheme.INSTANCE.getBackground()); lblName = new JLabel("Name"); txtName = new JTextField(); @@ -85,29 +85,12 @@ private void createUI() { btnConnect.addActionListener(this.connectAction); btnCancel.addActionListener(this.cancelAction); - tabbedPanel = new TabbedPanel( - false, - false, - new Color(52, 117, 233), - AppTheme.INSTANCE.getDarkControlBackground(), - new Color(52, 117, 233), - new Color(100, 100, 100), - AppTheme.INSTANCE.getBackground(), - AppTheme.INSTANCE.getDarkControlBackground(), - new Color(130, 130, 130), - new Color(180, 180, 180), - null, - AppTheme.INSTANCE.getSplitPaneBackground(), - null, - false, - true, - false - ); - - tabbedPanel.addTab("SSH", null, sshInfoPanel); - tabbedPanel.addTab("Proxy", null, new JPanel()); - tabbedPanel.addTab("Jump hosts", null, new JPanel()); - tabbedPanel.addTab("Port forwarding", null, new JPanel()); + tabbedPanel = new JTabbedPane(); + + tabbedPanel.addTab("SSH", sshInfoPanel); + tabbedPanel.addTab("Proxy", new JPanel()); + tabbedPanel.addTab("Jump hosts", new JPanel()); + tabbedPanel.addTab("Port forwarding", new JPanel()); tabbedPanel.setSelectedIndex(0); var hbox1 = Box.createHorizontalBox(); diff --git a/app/src/main/java/muon/screens/sessionmgr/SessionManager.java b/app/src/main/java/muon/screens/sessionmgr/SessionManager.java index 6ddeacdb..1f1215b3 100644 --- a/app/src/main/java/muon/screens/sessionmgr/SessionManager.java +++ b/app/src/main/java/muon/screens/sessionmgr/SessionManager.java @@ -14,8 +14,7 @@ public class SessionManager { public static SessionInfo showDialog(Window window) { var mgr = new SessionManagerPanel(); - var dlg = AppUtils.isWindows() ? new CustomDialog(window, "Session Manager") - : new JDialog(window, "Session Manager"); + var dlg = new JDialog(window, "Session Manager"); dlg.setModal(true); dlg.setSize(800, 600); dlg.setLocationRelativeTo(window); diff --git a/app/src/main/java/muon/screens/sessionmgr/SessionTreePanel.java b/app/src/main/java/muon/screens/sessionmgr/SessionTreePanel.java index 5700e46a..a9e84071 100644 --- a/app/src/main/java/muon/screens/sessionmgr/SessionTreePanel.java +++ b/app/src/main/java/muon/screens/sessionmgr/SessionTreePanel.java @@ -6,6 +6,7 @@ import muon.dto.session.SessionInfo; import muon.styles.AppTheme; import muon.styles.FlatTreeRenderer; +import muon.util.AppUtils; import muon.widgets.AutoScrollingJTree; import muon.util.IconCode; import muon.util.IconFont; @@ -32,7 +33,6 @@ public class SessionTreePanel extends JPanel { public SessionTreePanel(TreeSelectionListener selectionListener) { super(new BorderLayout()); - setBackground(AppTheme.INSTANCE.getBackground()); createUI(selectionListener); } @@ -100,38 +100,18 @@ private boolean selectNode(String id, DefaultMutableTreeNode node) { private void createUI(TreeSelectionListener selectionListener) { var treeScroll1 = new JScrollPane(createSessionTree(selectionListener)); - treeScroll1.setBorder(new EmptyBorder(0, 0, 0, 0)); - - var tabbedPanel = new TabbedPanel( - true, - false, - new Color(52, 117, 233), - AppTheme.INSTANCE.getDarkControlBackground(), - new Color(52, 117, 233), - AppTheme.INSTANCE.getDisabledForeground(), - AppTheme.INSTANCE.getBackground(), - AppTheme.INSTANCE.getDarkControlBackground(), - AppTheme.INSTANCE.getForeground(), - AppTheme.INSTANCE.getTitleForeground(), - null, - AppTheme.INSTANCE.getButtonBorderColor(), - null, - true, - true, - true - ); var hostTreePanel = new JPanel(new BorderLayout()); + hostTreePanel.setBorder(new EmptyBorder(10, 10, 10, 10)); hostTreePanel.add(createTreeTools(), BorderLayout.NORTH); hostTreePanel.add(treeScroll1); - tabbedPanel.addTab("Hosts", IconCode.RI_DATABASE_2_LINE, - hostTreePanel); - tabbedPanel.addTab("Recent", IconCode.RI_HISTORY_LINE, - new JPanel()); - - add(tabbedPanel); - + var tabs = new JTabbedPane(); + tabs.putClientProperty("JTabbedPane.tabAreaAlignment", "fill"); + tabs.setTabPlacement(JTabbedPane.BOTTOM); + tabs.addTab("Hosts", AppUtils.createSVGIcon("database-2-line.svg", 18, Color.GRAY), hostTreePanel); + tabs.addTab("Recent", AppUtils.createSVGIcon("history-line.svg", 18, Color.GRAY), new JPanel()); + add(tabs); } private JTree createSessionTree(TreeSelectionListener selectionListener) { @@ -140,31 +120,32 @@ private JTree createSessionTree(TreeSelectionListener selectionListener) { treeModel = new DefaultTreeModel(null, true); tree = new AutoScrollingJTree(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); - } - } - } - } - } - } - }); +// 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.setShowsRootHandles(false); + tree.setRowHeight(renderer.getPreferredSize().height); + tree.putClientProperty("JTree.showDefaultIcons", true); tree.setRootVisible(true); tree.setDragEnabled(true); tree.setEditable(false); @@ -174,15 +155,16 @@ public void mouseClicked(MouseEvent e) { tree.getSelectionModel().addTreeSelectionListener(selectionListener); tree.getSelectionModel().addTreeSelectionListener(e -> { var hasSelection = false; + if (Objects.isNull(e.getNewLeadSelectionPath())) { + return; + } if (Objects.nonNull(e.getNewLeadSelectionPath()) && Objects.nonNull(e.getNewLeadSelectionPath().getLastPathComponent())) { hasSelection = true; } + var node = (DefaultMutableTreeNode) e.getNewLeadSelectionPath().getLastPathComponent(); btnDelete.setEnabled(hasSelection && node != rootNode); - btnDelete.setForeground(hasSelection && node != rootNode - ? AppTheme.INSTANCE.getDarkForeground() - : AppTheme.INSTANCE.getDisabledForeground()); var nodeInfo = (NamedItem) node.getUserObject(); if (Objects.nonNull(nodeInfo)) { this.lastSelectedId = nodeInfo.getId(); @@ -221,16 +203,16 @@ private void selectNode(DefaultMutableTreeNode node) { } private Component createTreeTools() { - btnAddHost = createButton(IconCode.RI_FILE_ADD_LINE); - btnAddFolder = createButton(IconCode.RI_FOLDER_ADD_LINE); - btnDelete = createButton(IconCode.RI_DELETE_BIN_LINE); - btnClone = createButton(IconCode.RI_FILE_COPY_2_LINE); - btnImport = createButton(IconCode.RI_INSTALL_LINE); - btnExport = createButton(IconCode.RI_UNINSTALL_LINE); + btnAddHost = new JButton(AppUtils.createSVGIcon("file-add-fill.svg", 16, Color.GRAY));// createButton(IconCode.RI_FILE_ADD_LINE); + btnAddFolder = new JButton(AppUtils.createSVGIcon("folder-add-fill.svg", 16, Color.GRAY));//createButton(IconCode.RI_FOLDER_ADD_LINE); + btnDelete = new JButton(AppUtils.createSVGIcon("delete-bin-6-fill.svg", 16, Color.GRAY));//createButton(IconCode.RI_DELETE_BIN_LINE); + btnClone = new JButton(AppUtils.createSVGIcon("file-copy-2-fill.svg", 16, Color.GRAY));//createButton(IconCode.RI_FILE_COPY_2_LINE); + btnImport = new JButton(AppUtils.createSVGIcon("install-fill.svg", 16, Color.GRAY));//createButton(IconCode.RI_INSTALL_LINE); + btnExport = new JButton(AppUtils.createSVGIcon("uninstall-fill.svg", 16, Color.GRAY));//createButton(IconCode.RI_UNINSTALL_LINE); txtSearch = new JTextField(); - btnDelete.setForeground(AppTheme.INSTANCE.getDisabledForeground()); - btnClone.setForeground(AppTheme.INSTANCE.getDisabledForeground()); + btnDelete.setEnabled(false); + btnClone.setEnabled(false); btnAddHost.addActionListener(e -> { DefaultMutableTreeNode node = getSelectedFolder(); @@ -269,27 +251,19 @@ private Component createTreeTools() { } }); - var hbox1 = Box.createHorizontalBox(); - hbox1.add(btnAddHost); - hbox1.add(btnAddFolder); - hbox1.add(btnDelete); - hbox1.add(btnClone); - hbox1.add(Box.createHorizontalGlue()); - hbox1.add(btnImport); - hbox1.add(btnExport); - - var hbox2 = Box.createHorizontalBox(); - hbox2.add(Box.createRigidArea(new Dimension(3, 2))); - hbox2.add(txtSearch); - hbox2.add(Box.createRigidArea(new Dimension(3, 2))); + var toolbar = new JToolBar(); + toolbar.add(btnAddHost); + toolbar.add(btnAddFolder); + toolbar.add(btnDelete); + toolbar.add(btnClone); + toolbar.add(Box.createHorizontalGlue()); + toolbar.add(btnImport); + toolbar.add(btnExport); var vbox = Box.createVerticalBox(); - vbox.setBorder( - new EmptyBorder(7, 10, 10, 10) - ); - vbox.add(hbox1); + vbox.add(toolbar); + vbox.add(txtSearch); vbox.add(Box.createRigidArea(new Dimension(10, 5))); - vbox.add(hbox2); return vbox; } diff --git a/app/src/main/java/muon/service/SftpUploadTask.java b/app/src/main/java/muon/service/SftpUploadTask.java index ba5e2ce6..cf8042b0 100644 --- a/app/src/main/java/muon/service/SftpUploadTask.java +++ b/app/src/main/java/muon/service/SftpUploadTask.java @@ -49,7 +49,7 @@ public boolean isConnected() { return this.sftp.isConnected(); } - public void connect(InputBlocker inputBlocker) throws FSConnectException { + public void connect() throws FSConnectException { var passwordUserAuthFactory = new GuiUserAuthFactory(this.sftp.getSessionInfo()); var callback = new SshCallback(this.sftp.getSessionInfo()); this.sftp.connect(callback, passwordUserAuthFactory); diff --git a/app/src/main/java/muon/styles/AppTheme.java b/app/src/main/java/muon/styles/AppTheme.java index e06adceb..cff8e19f 100644 --- a/app/src/main/java/muon/styles/AppTheme.java +++ b/app/src/main/java/muon/styles/AppTheme.java @@ -89,98 +89,98 @@ public Color getListIconColor() { return new Color(0, 120, 212); } - public Object[] getDefaultStyles() { - Font widgetFont = new Font(Font.DIALOG, Font.PLAIN, 12); - return new Object[]{ - "Button.font", widgetFont, - "Button.background", getButtonBackground(), - "Button.disabledForeground", getDisabledForeground(), - "Button.foreground", getForeground(), - "Button.light", getButtonRollOverBackground(), - "Button.highlight", getButtonPressedBackground(), - "Button.border", new EmptyBorder(new Insets(5, 15, 5, 15)), - - "CheckBox.font", widgetFont, - "CheckBox.background", getBackground(), - "CheckBox.foreground", getForeground(), - "CheckBox.border", new EmptyBorder(new Insets(0, 0, 0, 0)), - - "ProgressBar.foreground", getSelectionColor(), - "ProgressBar.selectionBackground", getButtonPressedBackground(), - "ProgressBar.border", null, - - "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 EmptyBorder(5, 5, 5, 5), - "PasswordField.foreground", getForeground(), - "PasswordField.selectionBackground", getSelectionColor(), - "PasswordField.selectionForeground", getSelectionForeground(), - "PasswordField.caretForeground", getForeground(), - - "TextArea.background", getBackground(), - "TextArea.border", new EmptyBorder(5, 5, 5, 5), - "TextArea.foreground", getForeground(), - "TextArea.selectionBackground", getSelectionColor(), - "TextArea.selectionForeground", getSelectionForeground(), - "TextArea.caretForeground", getForeground(), - - "Tree.background", getBackground(), - "Tree.foreground", getForeground(), -// "Tree.openIcon", new FontIcon(IconCode.RI_FOLDER_OPEN_FILL, -// 24, 24, 16.0f, getForeground()), -// "Tree.closedIcon", new FontIcon(IconCode.RI_FOLDER_FILL, -// 24, 24, 16.0f, getForeground()), -// "Tree.leafIcon", new FontIcon(IconCode.RI_CLOSE_LINE, -// 24, 24, 16.0f, getForeground()), - "Tree.selectionForeground", getSelectionForeground(), - "Tree.textForeground", getForeground(), - "Tree.selectionBackground", getListSelectionColor(), - "Tree.textBackground", getBackground(), - "Tree.rendererFillBackground", true, - "Tree.lineStyle", "None", - "Tree.rightChildIndent", 10, - //"Tree.rendererMargins", new Insets(25,25,5,5), - "Tree.selectionBorderColor", getListSelectionColor(), - - "SplitPane.background", getButtonBorderColor(), - "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), - - "List.background", getBackground(), - "List.selectionBackground", getListSelectionColor(), - "List.selectionForeground", getSelectionForeground(), - "List.foreground", getForeground(), - "List.border", new EmptyBorder(0, 0, 0, 0), - - "ScrollPane.background", getBackground(), - "ScrollPane.foreground", getForeground(), - "ScrollPane.border", new EmptyBorder(0, 0, 0, 0), - - "Panel.background", getBackground(), - - "ScrollBar.width", 12, -// "ScrollBar.maximumThumbSize", new Dimension(5, 5), - "ScrollBar.minimumThumbSize", new Dimension(12, 12), - }; - } +// public Object[] getDefaultStyles() { +// Font widgetFont = new Font(Font.DIALOG, Font.PLAIN, 12); +// return new Object[]{ +// "Button.font", widgetFont, +// "Button.background", getButtonBackground(), +// "Button.disabledForeground", getDisabledForeground(), +// "Button.foreground", getForeground(), +// "Button.light", getButtonRollOverBackground(), +// "Button.highlight", getButtonPressedBackground(), +// "Button.border", new EmptyBorder(new Insets(5, 15, 5, 15)), +// +// "CheckBox.font", widgetFont, +// "CheckBox.background", getBackground(), +// "CheckBox.foreground", getForeground(), +// "CheckBox.border", new EmptyBorder(new Insets(0, 0, 0, 0)), +// +// "ProgressBar.foreground", getSelectionColor(), +// "ProgressBar.selectionBackground", getButtonPressedBackground(), +// "ProgressBar.border", null, +// +// "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 EmptyBorder(5, 5, 5, 5), +// "PasswordField.foreground", getForeground(), +// "PasswordField.selectionBackground", getSelectionColor(), +// "PasswordField.selectionForeground", getSelectionForeground(), +// "PasswordField.caretForeground", getForeground(), +// +// "TextArea.background", getBackground(), +// "TextArea.border", new EmptyBorder(5, 5, 5, 5), +// "TextArea.foreground", getForeground(), +// "TextArea.selectionBackground", getSelectionColor(), +// "TextArea.selectionForeground", getSelectionForeground(), +// "TextArea.caretForeground", getForeground(), +// +// "Tree.background", getBackground(), +// "Tree.foreground", getForeground(), +//// "Tree.openIcon", new FontIcon(IconCode.RI_FOLDER_OPEN_FILL, +//// 24, 24, 16.0f, getForeground()), +//// "Tree.closedIcon", new FontIcon(IconCode.RI_FOLDER_FILL, +//// 24, 24, 16.0f, getForeground()), +//// "Tree.leafIcon", new FontIcon(IconCode.RI_CLOSE_LINE, +//// 24, 24, 16.0f, getForeground()), +// "Tree.selectionForeground", getSelectionForeground(), +// "Tree.textForeground", getForeground(), +// "Tree.selectionBackground", getListSelectionColor(), +// "Tree.textBackground", getBackground(), +// "Tree.rendererFillBackground", true, +// "Tree.lineStyle", "None", +// "Tree.rightChildIndent", 10, +// //"Tree.rendererMargins", new Insets(25,25,5,5), +// "Tree.selectionBorderColor", getListSelectionColor(), +// +// "SplitPane.background", getButtonBorderColor(), +// "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), +// +// "List.background", getBackground(), +// "List.selectionBackground", getListSelectionColor(), +// "List.selectionForeground", getSelectionForeground(), +// "List.foreground", getForeground(), +// "List.border", new EmptyBorder(0, 0, 0, 0), +// +// "ScrollPane.background", getBackground(), +// "ScrollPane.foreground", getForeground(), +// "ScrollPane.border", new EmptyBorder(0, 0, 0, 0), +// +// "Panel.background", getBackground(), +// +// "ScrollBar.width", 12, +//// "ScrollBar.maximumThumbSize", new Dimension(5, 5), +// "ScrollBar.minimumThumbSize", new Dimension(12, 12), +// }; +// } } diff --git a/app/src/main/java/muon/styles/FlatLookAndFeel.java b/app/src/main/java/muon/styles/FlatLookAndFeel.java index 70d93d9d..1199c9d3 100644 --- a/app/src/main/java/muon/styles/FlatLookAndFeel.java +++ b/app/src/main/java/muon/styles/FlatLookAndFeel.java @@ -25,7 +25,7 @@ public void initClassDefaults(UIDefaults table) { protected void initComponentDefaults(UIDefaults table) { super.initComponentDefaults(table); - table.putDefaults(AppTheme.INSTANCE.getDefaultStyles()); + //table.putDefaults(AppTheme.INSTANCE.getDefaultStyles()); } @Override diff --git a/app/src/main/java/muon/styles/FlatTreeRenderer.java b/app/src/main/java/muon/styles/FlatTreeRenderer.java index 189ee1a4..8ffbecbd 100644 --- a/app/src/main/java/muon/styles/FlatTreeRenderer.java +++ b/app/src/main/java/muon/styles/FlatTreeRenderer.java @@ -1,100 +1,35 @@ package muon.styles; +import muon.dto.session.SessionInfo; +import muon.util.AppUtils; 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.TreeCellRenderer; import java.awt.*; -public class FlatTreeRenderer implements TreeCellRenderer { - private JPanel panel; - private JLabel expandArrow, collapsedArrow, nodeIcon, leafIcon, text; - private Component blank; +public class FlatTreeRenderer extends JLabel implements TreeCellRenderer { + private Icon fileIcon, folderIcon; 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_FILL); - 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; + setOpaque(true); + setBorder(new EmptyBorder(5, 5, 5, 5)); + setIconTextGap(10); + fileIcon = AppUtils.createSVGIcon("file-2-fill.svg", 20, AppTheme.INSTANCE.getListIconColor()); + folderIcon = AppUtils.createSVGIcon("folder-fill.svg", 20, AppTheme.INSTANCE.getListIconColor()); + setIcon(fileIcon); + setText("Sample text"); } @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.getDarkForeground()); - leafIcon.setForeground(selected ? AppTheme.INSTANCE.getSelectionForeground() : AppTheme.INSTANCE.getDarkForeground()); - 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; + setText(value.toString()); + setIcon(((DefaultMutableTreeNode) value).getUserObject() instanceof SessionInfo ? fileIcon : folderIcon); + setBackground(selected ? UIManager.getColor("Tree.selectionBackground") : tree.getBackground()); + setForeground(selected ? UIManager.getColor("Tree.selectionForeground") : tree.getForeground()); + return this; } } diff --git a/app/src/main/java/muon/util/AppUtils.java b/app/src/main/java/muon/util/AppUtils.java index b6fc075d..88254897 100644 --- a/app/src/main/java/muon/util/AppUtils.java +++ b/app/src/main/java/muon/util/AppUtils.java @@ -1,5 +1,6 @@ package muon.util; +import com.formdev.flatlaf.extras.FlatSVGIcon; import muon.constants.AppConstant; import muon.dto.session.SessionInfo; import muon.styles.AppTheme; @@ -9,6 +10,7 @@ import javax.swing.border.EmptyBorder; import java.awt.*; import java.awt.event.MouseEvent; +import java.io.IOException; import java.nio.file.attribute.BasicFileAttributes; import java.time.LocalDateTime; import java.time.ZoneId; @@ -66,6 +68,25 @@ public static JButton createIconButton(IconCode iconCode) { return createIconButton(iconCode, 18.0f); } + public static FlatSVGIcon createSVGIcon(String name, int size, Color color) { + FlatSVGIcon.ColorFilter filter = new FlatSVGIcon.ColorFilter(); + filter.add(Color.BLACK, color); + try { + var icon = new FlatSVGIcon(AppUtils.class.getResourceAsStream("/icons/" + name)); + icon.setColorFilter(filter); + return icon.derive(size, size); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static JButton createIconToolbarButton(IconCode iconCode) { + var button = new JButton(); + button.setFont(IconFont.getSharedInstance().getIconFont(18.0f)); + button.setText(iconCode.getValue()); + return button; + } + public static JButton createIconButton(IconCode iconCode, float iconSize) { var button = new JButton(); button.setBorderPainted(false); diff --git a/app/src/main/resources/icons/add-line.svg b/app/src/main/resources/icons/add-line.svg new file mode 100644 index 00000000..669cd66e --- /dev/null +++ b/app/src/main/resources/icons/add-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/src/main/resources/icons/arrow_back_black_24dp.svg b/app/src/main/resources/icons/arrow_back_black_24dp.svg new file mode 100644 index 00000000..74597028 --- /dev/null +++ b/app/src/main/resources/icons/arrow_back_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/src/main/resources/icons/arrow_forward_black_24dp.svg b/app/src/main/resources/icons/arrow_forward_black_24dp.svg new file mode 100644 index 00000000..3ff6b4c0 --- /dev/null +++ b/app/src/main/resources/icons/arrow_forward_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/src/main/resources/icons/arrow_upward_black_24dp.svg b/app/src/main/resources/icons/arrow_upward_black_24dp.svg new file mode 100644 index 00000000..02a01a7a --- /dev/null +++ b/app/src/main/resources/icons/arrow_upward_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/src/main/resources/icons/autorenew_black_24dp.svg b/app/src/main/resources/icons/autorenew_black_24dp.svg new file mode 100644 index 00000000..534a8c98 --- /dev/null +++ b/app/src/main/resources/icons/autorenew_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/src/main/resources/icons/database-2-line.svg b/app/src/main/resources/icons/database-2-line.svg new file mode 100644 index 00000000..166d445a --- /dev/null +++ b/app/src/main/resources/icons/database-2-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/src/main/resources/icons/delete-bin-6-fill.svg b/app/src/main/resources/icons/delete-bin-6-fill.svg new file mode 100644 index 00000000..00cf709b --- /dev/null +++ b/app/src/main/resources/icons/delete-bin-6-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/src/main/resources/icons/file-2-fill.svg b/app/src/main/resources/icons/file-2-fill.svg new file mode 100644 index 00000000..1342095a --- /dev/null +++ b/app/src/main/resources/icons/file-2-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/src/main/resources/icons/file-add-fill.svg b/app/src/main/resources/icons/file-add-fill.svg new file mode 100644 index 00000000..e3676691 --- /dev/null +++ b/app/src/main/resources/icons/file-add-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/src/main/resources/icons/file-copy-2-fill.svg b/app/src/main/resources/icons/file-copy-2-fill.svg new file mode 100644 index 00000000..991550df --- /dev/null +++ b/app/src/main/resources/icons/file-copy-2-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/src/main/resources/icons/folder-add-fill.svg b/app/src/main/resources/icons/folder-add-fill.svg new file mode 100644 index 00000000..618d701e --- /dev/null +++ b/app/src/main/resources/icons/folder-add-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/src/main/resources/icons/folder-fill.svg b/app/src/main/resources/icons/folder-fill.svg new file mode 100644 index 00000000..540f849a --- /dev/null +++ b/app/src/main/resources/icons/folder-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/src/main/resources/icons/history-line.svg b/app/src/main/resources/icons/history-line.svg new file mode 100644 index 00000000..462997cb --- /dev/null +++ b/app/src/main/resources/icons/history-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/src/main/resources/icons/home_black_24dp.svg b/app/src/main/resources/icons/home_black_24dp.svg new file mode 100644 index 00000000..8584f7eb --- /dev/null +++ b/app/src/main/resources/icons/home_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/src/main/resources/icons/install-fill.svg b/app/src/main/resources/icons/install-fill.svg new file mode 100644 index 00000000..ae5ad433 --- /dev/null +++ b/app/src/main/resources/icons/install-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/src/main/resources/icons/key-fill.svg b/app/src/main/resources/icons/key-fill.svg new file mode 100644 index 00000000..99a191f6 --- /dev/null +++ b/app/src/main/resources/icons/key-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/src/main/resources/icons/language_black_24dp.svg b/app/src/main/resources/icons/language_black_24dp.svg new file mode 100644 index 00000000..65881a88 --- /dev/null +++ b/app/src/main/resources/icons/language_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/src/main/resources/icons/laptop_black_24dp.svg b/app/src/main/resources/icons/laptop_black_24dp.svg new file mode 100644 index 00000000..547ac26c --- /dev/null +++ b/app/src/main/resources/icons/laptop_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/src/main/resources/icons/more_vert_black_24dp.svg b/app/src/main/resources/icons/more_vert_black_24dp.svg new file mode 100644 index 00000000..f226ebff --- /dev/null +++ b/app/src/main/resources/icons/more_vert_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/src/main/resources/icons/refresh_black_24dp.svg b/app/src/main/resources/icons/refresh_black_24dp.svg new file mode 100644 index 00000000..e217f035 --- /dev/null +++ b/app/src/main/resources/icons/refresh_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/src/main/resources/icons/search_black_24dp.svg b/app/src/main/resources/icons/search_black_24dp.svg new file mode 100644 index 00000000..14655596 --- /dev/null +++ b/app/src/main/resources/icons/search_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/src/main/resources/icons/swap-box-fill.svg b/app/src/main/resources/icons/swap-box-fill.svg new file mode 100644 index 00000000..c22ed648 --- /dev/null +++ b/app/src/main/resources/icons/swap-box-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/src/main/resources/icons/sync_black_24dp.svg b/app/src/main/resources/icons/sync_black_24dp.svg new file mode 100644 index 00000000..7e10ba16 --- /dev/null +++ b/app/src/main/resources/icons/sync_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/src/main/resources/icons/terminal-box-fill.svg b/app/src/main/resources/icons/terminal-box-fill.svg new file mode 100644 index 00000000..771c6f54 --- /dev/null +++ b/app/src/main/resources/icons/terminal-box-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/src/main/resources/icons/uninstall-fill.svg b/app/src/main/resources/icons/uninstall-fill.svg new file mode 100644 index 00000000..3ff3bed2 --- /dev/null +++ b/app/src/main/resources/icons/uninstall-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/target/classes/icons/add-line.svg b/app/target/classes/icons/add-line.svg new file mode 100644 index 00000000..669cd66e --- /dev/null +++ b/app/target/classes/icons/add-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/target/classes/icons/arrow_back_black_24dp.svg b/app/target/classes/icons/arrow_back_black_24dp.svg new file mode 100644 index 00000000..74597028 --- /dev/null +++ b/app/target/classes/icons/arrow_back_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/target/classes/icons/arrow_forward_black_24dp.svg b/app/target/classes/icons/arrow_forward_black_24dp.svg new file mode 100644 index 00000000..3ff6b4c0 --- /dev/null +++ b/app/target/classes/icons/arrow_forward_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/target/classes/icons/arrow_upward_black_24dp.svg b/app/target/classes/icons/arrow_upward_black_24dp.svg new file mode 100644 index 00000000..02a01a7a --- /dev/null +++ b/app/target/classes/icons/arrow_upward_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/target/classes/icons/autorenew_black_24dp.svg b/app/target/classes/icons/autorenew_black_24dp.svg new file mode 100644 index 00000000..534a8c98 --- /dev/null +++ b/app/target/classes/icons/autorenew_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/target/classes/icons/database-2-line.svg b/app/target/classes/icons/database-2-line.svg new file mode 100644 index 00000000..166d445a --- /dev/null +++ b/app/target/classes/icons/database-2-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/target/classes/icons/delete-bin-6-fill.svg b/app/target/classes/icons/delete-bin-6-fill.svg new file mode 100644 index 00000000..00cf709b --- /dev/null +++ b/app/target/classes/icons/delete-bin-6-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/target/classes/icons/file-2-fill.svg b/app/target/classes/icons/file-2-fill.svg new file mode 100644 index 00000000..1342095a --- /dev/null +++ b/app/target/classes/icons/file-2-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/target/classes/icons/file-add-fill.svg b/app/target/classes/icons/file-add-fill.svg new file mode 100644 index 00000000..e3676691 --- /dev/null +++ b/app/target/classes/icons/file-add-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/target/classes/icons/file-copy-2-fill.svg b/app/target/classes/icons/file-copy-2-fill.svg new file mode 100644 index 00000000..991550df --- /dev/null +++ b/app/target/classes/icons/file-copy-2-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/target/classes/icons/folder-add-fill.svg b/app/target/classes/icons/folder-add-fill.svg new file mode 100644 index 00000000..618d701e --- /dev/null +++ b/app/target/classes/icons/folder-add-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/target/classes/icons/folder-fill.svg b/app/target/classes/icons/folder-fill.svg new file mode 100644 index 00000000..540f849a --- /dev/null +++ b/app/target/classes/icons/folder-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/target/classes/icons/history-line.svg b/app/target/classes/icons/history-line.svg new file mode 100644 index 00000000..462997cb --- /dev/null +++ b/app/target/classes/icons/history-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/target/classes/icons/home_black_24dp.svg b/app/target/classes/icons/home_black_24dp.svg new file mode 100644 index 00000000..8584f7eb --- /dev/null +++ b/app/target/classes/icons/home_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/target/classes/icons/install-fill.svg b/app/target/classes/icons/install-fill.svg new file mode 100644 index 00000000..ae5ad433 --- /dev/null +++ b/app/target/classes/icons/install-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/target/classes/icons/key-fill.svg b/app/target/classes/icons/key-fill.svg new file mode 100644 index 00000000..99a191f6 --- /dev/null +++ b/app/target/classes/icons/key-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/target/classes/icons/language_black_24dp.svg b/app/target/classes/icons/language_black_24dp.svg new file mode 100644 index 00000000..65881a88 --- /dev/null +++ b/app/target/classes/icons/language_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/target/classes/icons/laptop_black_24dp.svg b/app/target/classes/icons/laptop_black_24dp.svg new file mode 100644 index 00000000..547ac26c --- /dev/null +++ b/app/target/classes/icons/laptop_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/target/classes/icons/more_vert_black_24dp.svg b/app/target/classes/icons/more_vert_black_24dp.svg new file mode 100644 index 00000000..f226ebff --- /dev/null +++ b/app/target/classes/icons/more_vert_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/target/classes/icons/refresh_black_24dp.svg b/app/target/classes/icons/refresh_black_24dp.svg new file mode 100644 index 00000000..e217f035 --- /dev/null +++ b/app/target/classes/icons/refresh_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/target/classes/icons/search_black_24dp.svg b/app/target/classes/icons/search_black_24dp.svg new file mode 100644 index 00000000..14655596 --- /dev/null +++ b/app/target/classes/icons/search_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/target/classes/icons/swap-box-fill.svg b/app/target/classes/icons/swap-box-fill.svg new file mode 100644 index 00000000..c22ed648 --- /dev/null +++ b/app/target/classes/icons/swap-box-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/target/classes/icons/sync_black_24dp.svg b/app/target/classes/icons/sync_black_24dp.svg new file mode 100644 index 00000000..7e10ba16 --- /dev/null +++ b/app/target/classes/icons/sync_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/target/classes/icons/terminal-box-fill.svg b/app/target/classes/icons/terminal-box-fill.svg new file mode 100644 index 00000000..771c6f54 --- /dev/null +++ b/app/target/classes/icons/terminal-box-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/target/classes/icons/uninstall-fill.svg b/app/target/classes/icons/uninstall-fill.svg new file mode 100644 index 00000000..3ff3bed2 --- /dev/null +++ b/app/target/classes/icons/uninstall-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/target/surefire-reports/TEST-muon.AppTest.xml b/app/target/surefire-reports/TEST-muon.AppTest.xml index a576c81e..bf6eeffb 100644 --- a/app/target/surefire-reports/TEST-muon.AppTest.xml +++ b/app/target/surefire-reports/TEST-muon.AppTest.xml @@ -1,9 +1,9 @@ - + - + @@ -12,10 +12,10 @@ - + - + @@ -57,5 +57,5 @@ - + \ No newline at end of file diff --git a/app/target/surefire-reports/muon.AppTest.txt b/app/target/surefire-reports/muon.AppTest.txt index 2dc3a634..9340c6b0 100644 --- a/app/target/surefire-reports/muon.AppTest.txt +++ b/app/target/surefire-reports/muon.AppTest.txt @@ -1,4 +1,4 @@ ------------------------------------------------------------------------------- Test set: muon.AppTest ------------------------------------------------------------------------------- -Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.125 s - in muon.AppTest +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.124 s - in muon.AppTest