diff --git a/src/main/java/cz/kamma/kfmanager/ui/FilePanel.java b/src/main/java/cz/kamma/kfmanager/ui/FilePanel.java index d67ae85..8018ef4 100644 --- a/src/main/java/cz/kamma/kfmanager/ui/FilePanel.java +++ b/src/main/java/cz/kamma/kfmanager/ui/FilePanel.java @@ -76,6 +76,8 @@ public class FilePanel extends JPanel { private void initComponents() { tabbedPane = new JTabbedPane(); + tabbedPane.putClientProperty("JTabbedPane.showTabSeparators", true); + tabbedPane.putClientProperty("JTabbedPane.hasFullBorder", true); setLayout(new BorderLayout()); setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); @@ -627,10 +629,12 @@ public class FilePanel extends JPanel { // Inactive indicator is subtle dark gray Color inactiveColor = new Color(60, 60, 60); Color targetColor = active ? activeColor : inactiveColor; - - // Apply a matte border to the top of tabbedPane - this places it between - // the topPanel (dropdown) and the tabs themselves. - tabbedPane.setBorder(BorderFactory.createMatteBorder(3, 0, 0, 0, targetColor)); + + // Remove the horizontal line above tabs. + tabbedPane.setBorder(null); + + // No panel border highlight. + setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); // Propagate active state to all tabs for (int i = 0; i < tabbedPane.getTabCount(); i++) { @@ -650,6 +654,13 @@ public class FilePanel extends JPanel { private void updateTabStyles() { if (tabbedPane == null) return; int selectedIndex = tabbedPane.getSelectedIndex(); + Color baseTabColor = UIManager.getColor("TabbedPane.background"); + if (baseTabColor == null) { + baseTabColor = tabbedPane.getBackground(); + } + Color inactiveTabColor = adjustBrightness(baseTabColor, -0.08f); + Color activeTabColor = adjustBrightness(baseTabColor, 0.10f); + for (int i = 0; i < tabbedPane.getTabCount(); i++) { Component c = tabbedPane.getComponentAt(i); if (c instanceof FilePanelTab tab) { @@ -657,17 +668,29 @@ public class FilePanel extends JPanel { String title = getTabTitle(dir != null ? dir.getAbsolutePath() : ""); if (i == selectedIndex) { - // Active tab: bold font and dark blue color + // Active tab: bold font tabbedPane.setTitleAt(i, "" + title + ""); - tabbedPane.setForegroundAt(i, new Color(0, 51, 153)); + tabbedPane.setForegroundAt(i, null); + tabbedPane.setBackgroundAt(i, activeTabColor); } else { // Inactive tab: normal font and default color tabbedPane.setTitleAt(i, title); tabbedPane.setForegroundAt(i, null); + tabbedPane.setBackgroundAt(i, inactiveTabColor); } } } } + + private Color adjustBrightness(Color color, float delta) { + if (color == null) { + return null; + } + float[] hsb = Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), null); + float newBrightness = Math.max(0f, Math.min(1f, hsb[2] + delta)); + int rgb = Color.HSBtoRGB(hsb[0], hsb[1], newBrightness); + return new Color((rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF); + } /** * Remove the current tab @@ -965,6 +988,15 @@ public class FilePanel extends JPanel { } public void applySelectionColor(Color sel) { + if (sel != null) { + tabbedPane.putClientProperty("FlatLaf.style", "underlineColor: " + toHexColor(sel) + ";"); + } else { + tabbedPane.putClientProperty("FlatLaf.style", null); + } + // Fallback for non-FlatLaf implementations + tabbedPane.putClientProperty("JTabbedPane.underlineColor", sel); + updateTabStyles(); + tabbedPane.repaint(); for (int i = 0; i < tabbedPane.getTabCount(); i++) { Component c = tabbedPane.getComponentAt(i); if (c instanceof FilePanelTab tab) { @@ -973,6 +1005,11 @@ public class FilePanel extends JPanel { } } + private String toHexColor(Color color) { + if (color == null) return "#000000"; + return "#%02x%02x%02x".formatted(color.getRed(), color.getGreen(), color.getBlue()); + } + public void applyMarkedColor(Color mark) { for (int i = 0; i < tabbedPane.getTabCount(); i++) { Component c = tabbedPane.getComponentAt(i); diff --git a/src/main/java/cz/kamma/kfmanager/ui/FilePanelTab.java b/src/main/java/cz/kamma/kfmanager/ui/FilePanelTab.java index 6db8b92..206b0ce 100644 --- a/src/main/java/cz/kamma/kfmanager/ui/FilePanelTab.java +++ b/src/main/java/cz/kamma/kfmanager/ui/FilePanelTab.java @@ -51,7 +51,9 @@ public class FilePanelTab extends JPanel { private JPanel cardPanel; private CardLayout cardLayout; private JTextArea infoTextArea; + private JScrollPane tableScrollPane; private JScrollPane infoScrollPane; + private javax.swing.border.Border defaultTableScrollBorder; private int briefCurrentColumn = 0; private Runnable onDirectoryChanged; private Runnable onSwitchPanelRequested; @@ -269,6 +271,7 @@ public class FilePanelTab extends JPanel { public void applySelectionColor(Color sel) { if (sel == null) return; this.selectionColor = sel; + updateContentBorder(); fileTable.repaint(); } @@ -291,11 +294,27 @@ public class FilePanelTab extends JPanel { public void setActive(boolean active) { this.active = active; + updateContentBorder(); if (fileTable != null) { fileTable.repaint(); } } + private void updateContentBorder() { + if (tableScrollPane == null) { + return; + } + if (active && selectionColor != null) { + tableScrollPane.setBorder(BorderFactory.createLineBorder(selectionColor, 1)); + return; + } + if (defaultTableScrollBorder != null) { + tableScrollPane.setBorder(defaultTableScrollBorder); + return; + } + tableScrollPane.setBorder(UIManager.getBorder("ScrollPane.border")); + } + /** * Return true when focus belongs to one of the BRIEF sorting controls. */ @@ -781,15 +800,16 @@ public class FilePanelTab extends JPanel { } }); - JScrollPane scrollPane = new JScrollPane(fileTable); + tableScrollPane = new JScrollPane(fileTable); + defaultTableScrollBorder = tableScrollPane.getBorder(); // Enable horizontal scrollbar when needed so BRIEF mode can scroll left-right - scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + tableScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); // Increase scroll speed - scrollPane.getVerticalScrollBar().setUnitIncrement(30); - scrollPane.getHorizontalScrollBar().setUnitIncrement(30); - scrollPane.getVerticalScrollBar().setBlockIncrement(200); - scrollPane.getHorizontalScrollBar().setBlockIncrement(200); + tableScrollPane.getVerticalScrollBar().setUnitIncrement(30); + tableScrollPane.getHorizontalScrollBar().setUnitIncrement(30); + tableScrollPane.getVerticalScrollBar().setBlockIncrement(200); + tableScrollPane.getHorizontalScrollBar().setBlockIncrement(200); // Info panel for Quick View (Ctrl+Q) infoTextArea = new JTextArea(); @@ -800,7 +820,7 @@ public class FilePanelTab extends JPanel { cardLayout = new CardLayout(); cardPanel = new JPanel(cardLayout); - cardPanel.add(scrollPane, "TABLE"); + cardPanel.add(tableScrollPane, "TABLE"); cardPanel.add(infoScrollPane, "INFO"); // Implement mouse wheel scrolling without changing selection @@ -926,7 +946,7 @@ public class FilePanelTab extends JPanel { add(statusLabel, BorderLayout.SOUTH); // Add listener to handle panel resize - scrollPane.addComponentListener(new java.awt.event.ComponentAdapter() { + tableScrollPane.addComponentListener(new java.awt.event.ComponentAdapter() { @Override public void componentResized(java.awt.event.ComponentEvent e) { if (viewMode == ViewMode.BRIEF) {