menu improved

This commit is contained in:
Radek Davidek 2026-02-06 17:10:41 +01:00
parent 6abe0c5881
commit bf1ec599ee
2 changed files with 104 additions and 34 deletions

View File

@ -9,8 +9,8 @@
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
<properties> <properties>
<maven.compiler.source>17</maven.compiler.source> <maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target> <maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> </properties>
@ -29,8 +29,8 @@
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version> <version>3.11.0</version>
<configuration> <configuration>
<source>17</source> <source>11</source>
<target>17</target> <target>11</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>

View File

@ -88,6 +88,15 @@ public class KeepassApp extends JFrame {
private String currentPassword; private String currentPassword;
private TrayIcon trayIcon; private TrayIcon trayIcon;
// Menu items that need state management
private JMenuItem menuSave;
private JMenuItem menuLock;
private JMenuItem menuEntryAdd;
private JMenuItem menuEntryEdit;
private JMenuItem menuEntryDelete;
private JMenuItem menuEditCopyUser;
private JMenuItem menuEditCopyPass;
public KeepassApp() { public KeepassApp() {
@ -282,22 +291,22 @@ public class KeepassApp extends JFrame {
JMenu fileMenu = new JMenu("File"); JMenu fileMenu = new JMenu("File");
JMenuItem openItem = new JMenuItem("Open Database..."); JMenuItem openItem = new JMenuItem("Open Database...");
recentMenu = new JMenu("Open Recent"); recentMenu = new JMenu("Open Recent");
JMenuItem saveItem = new JMenuItem("Save"); menuSave = new JMenuItem("Save");
JMenuItem minimizeItem = new JMenuItem(SystemTray.isSupported() ? "Minimize to Tray" : "Minimize & Lock"); JMenuItem minimizeItem = new JMenuItem(SystemTray.isSupported() ? "Minimize to Tray" : "Minimize & Lock");
JMenuItem lockItem = new JMenuItem("Lock Database"); menuLock = new JMenuItem("Lock Database");
JMenuItem exitItem = new JMenuItem("Exit"); JMenuItem exitItem = new JMenuItem("Exit");
openItem.addActionListener(e -> openDatabase(null)); openItem.addActionListener(e -> openDatabase(null));
saveItem.addActionListener(e -> saveDatabase()); menuSave.addActionListener(e -> saveDatabase());
minimizeItem.addActionListener(e -> minimizeToCustomTray()); minimizeItem.addActionListener(e -> minimizeToCustomTray());
lockItem.addActionListener(e -> lockDatabase()); menuLock.addActionListener(e -> lockDatabase());
exitItem.addActionListener(e -> System.exit(0)); exitItem.addActionListener(e -> System.exit(0));
fileMenu.add(openItem); fileMenu.add(openItem);
fileMenu.add(recentMenu); fileMenu.add(recentMenu);
fileMenu.add(saveItem); fileMenu.add(menuSave);
fileMenu.addSeparator(); fileMenu.addSeparator();
fileMenu.add(lockItem); fileMenu.add(menuLock);
fileMenu.add(minimizeItem); fileMenu.add(minimizeItem);
fileMenu.add(exitItem); fileMenu.add(exitItem);
@ -305,40 +314,42 @@ public class KeepassApp extends JFrame {
// Entry Menu // Entry Menu
JMenu entryMenu = new JMenu("Entry"); JMenu entryMenu = new JMenu("Entry");
JMenuItem addItem = new JMenuItem("Add Entry..."); menuEntryAdd = new JMenuItem("Add Entry...");
JMenuItem editItem = new JMenuItem("Edit Entry..."); menuEntryEdit = new JMenuItem("Edit Entry...");
JMenuItem delItem = new JMenuItem("Delete Entry"); menuEntryDelete = new JMenuItem("Delete Entry");
addItem.addActionListener(e -> addEntry()); menuEntryAdd.addActionListener(e -> addEntry());
editItem.addActionListener(e -> editEntry()); menuEntryEdit.addActionListener(e -> editEntry());
delItem.addActionListener(e -> deleteEntry()); menuEntryDelete.addActionListener(e -> deleteEntry());
entryMenu.add(addItem); entryMenu.add(menuEntryAdd);
entryMenu.add(editItem); entryMenu.add(menuEntryEdit);
entryMenu.add(delItem); entryMenu.add(menuEntryDelete);
// Edit Menu // Edit Menu
JMenu editMenu = new JMenu("Edit"); JMenu editMenu = new JMenu("Edit");
JMenuItem copyUserItem = new JMenuItem("Copy Username"); menuEditCopyUser = new JMenuItem("Copy Username");
JMenuItem copyPassItem = new JMenuItem("Copy Password"); menuEditCopyPass = new JMenuItem("Copy Password");
copyUserItem.addActionListener(e -> copyToClipboard(true)); menuEditCopyUser.addActionListener(e -> copyToClipboard(true));
copyPassItem.addActionListener(e -> copyToClipboard(false)); menuEditCopyPass.addActionListener(e -> copyToClipboard(false));
editMenu.add(copyUserItem); editMenu.add(menuEditCopyUser);
editMenu.add(copyPassItem); editMenu.add(menuEditCopyPass);
// View Menu // View Menu
JMenu viewMenu = new JMenu("View"); JMenu viewMenu = new JMenu("View");
JCheckBoxMenuItem onTopItem = new JCheckBoxMenuItem("Always on Top"); JCheckBoxMenuItem onTopItem = new JCheckBoxMenuItem("Always on Top");
onTopItem.addActionListener(e -> setAlwaysOnTop(onTopItem.isSelected())); onTopItem.addActionListener(e -> setAlwaysOnTop(onTopItem.isSelected()));
viewMenu.add(onTopItem); viewMenu.add(onTopItem);
menuBar.add(fileMenu); menuBar.add(fileMenu);
menuBar.add(entryMenu); menuBar.add(entryMenu);
menuBar.add(editMenu); menuBar.add(editMenu);
menuBar.add(viewMenu); menuBar.add(viewMenu);
setJMenuBar(menuBar); setJMenuBar(menuBar);
// Initialize menu state (all disabled until database is loaded)
updateMenuState();
} }
private void initComponents() { private void initComponents() {
@ -350,6 +361,7 @@ public class KeepassApp extends JFrame {
DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) groupTree.getLastSelectedPathComponent(); DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) groupTree.getLastSelectedPathComponent();
if (selectedNode != null && selectedNode.getUserObject() instanceof GroupWrapper) { if (selectedNode != null && selectedNode.getUserObject() instanceof GroupWrapper) {
displayEntriesInGroup(((GroupWrapper) selectedNode.getUserObject()).getGroup()); displayEntriesInGroup(((GroupWrapper) selectedNode.getUserObject()).getGroup());
updateMenuState();
} }
}); });
groupTree.addMouseListener(new MouseAdapter() { groupTree.addMouseListener(new MouseAdapter() {
@ -419,6 +431,7 @@ public class KeepassApp extends JFrame {
} else { } else {
notesArea.setText(""); notesArea.setText("");
} }
updateMenuState();
} }
}); });
entryTable.addMouseListener(new MouseAdapter() { entryTable.addMouseListener(new MouseAdapter() {
@ -430,14 +443,26 @@ public class KeepassApp extends JFrame {
if (row >= 0 && col >= 0) { if (row >= 0 && col >= 0) {
int modelRow = entryTable.convertRowIndexToModel(row); int modelRow = entryTable.convertRowIndexToModel(row);
Entry entry = currentEntries.get(modelRow); Entry entry = currentEntries.get(modelRow);
String content = switch (col) { String content;
case 0 -> entry.getTitle(); switch (col) {
case 1 -> entry.getUsername(); case 0:
case 2 -> entry.getPassword(); content = entry.getTitle();
case 3 -> entry.getUrl(); break;
case 4 -> entry.getNotes(); case 1:
default -> ""; content = entry.getUsername();
}; break;
case 2:
content = entry.getPassword();
break;
case 3:
content = entry.getUrl();
break;
case 4:
content = entry.getNotes();
break;
default:
content = "";
}
copyTextToClipboard(content, entryTable.getColumnName(col)); copyTextToClipboard(content, entryTable.getColumnName(col));
} }
} }
@ -462,11 +487,20 @@ public class KeepassApp extends JFrame {
JPopupMenu popup = new JPopupMenu(); JPopupMenu popup = new JPopupMenu();
boolean hasGroup = currentGroup != null;
boolean hasEntry = row >= 0;
JMenuItem addPop = new JMenuItem("Add Entry"); JMenuItem addPop = new JMenuItem("Add Entry");
JMenuItem editPop = new JMenuItem("Edit"); JMenuItem editPop = new JMenuItem("Edit");
JMenuItem copyPop = new JMenuItem("Copy Username"); JMenuItem copyPop = new JMenuItem("Copy Username");
JMenuItem copyPassPop = new JMenuItem("Copy Password"); JMenuItem copyPassPop = new JMenuItem("Copy Password");
JMenuItem delPop = new JMenuItem("Delete"); JMenuItem delPop = new JMenuItem("Delete");
addPop.setEnabled(hasGroup);
editPop.setEnabled(hasEntry);
copyPop.setEnabled(hasEntry);
copyPassPop.setEnabled(hasEntry);
delPop.setEnabled(hasEntry);
addPop.addActionListener(al -> addEntry()); addPop.addActionListener(al -> addEntry());
editPop.addActionListener(al -> editEntry()); editPop.addActionListener(al -> editEntry());
@ -551,6 +585,35 @@ public class KeepassApp extends JFrame {
} }
} }
/**
* Update menu item enabled states based on current application state
*/
private void updateMenuState() {
// Safely check if menu items are initialized (they might not be during early init)
if (menuSave == null || menuLock == null || menuEntryAdd == null ||
menuEntryEdit == null || menuEntryDelete == null ||
menuEditCopyUser == null || menuEditCopyPass == null) {
return;
}
boolean dbIsLoaded = database != null;
boolean hasGroupSelected = currentGroup != null;
boolean hasEntrySelected = entryTable != null && entryTable.getSelectedRow() >= 0;
// File menu items
menuSave.setEnabled(dbIsLoaded);
menuLock.setEnabled(dbIsLoaded);
// Entry menu items
menuEntryAdd.setEnabled(dbIsLoaded && hasGroupSelected);
menuEntryEdit.setEnabled(hasEntrySelected);
menuEntryDelete.setEnabled(hasEntrySelected);
// Edit menu items
menuEditCopyUser.setEnabled(hasEntrySelected);
menuEditCopyPass.setEnabled(hasEntrySelected);
}
private void updateRecentMenu() { private void updateRecentMenu() {
recentMenu.removeAll(); recentMenu.removeAll();
String recentFiles = prefs.get(PREF_RECENT_LIST, ""); String recentFiles = prefs.get(PREF_RECENT_LIST, "");
@ -630,6 +693,7 @@ public class KeepassApp extends JFrame {
updateTree(this.database.getRootGroup()); updateTree(this.database.getRootGroup());
saveRecentFile(selectedFile.getAbsolutePath()); saveRecentFile(selectedFile.getAbsolutePath());
statusLabel.setText(" Database loaded: " + selectedFile.getName()); statusLabel.setText(" Database loaded: " + selectedFile.getName());
updateMenuState();
} catch (Exception ex) { } catch (Exception ex) {
JOptionPane.showMessageDialog(this, "Error loading database: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(this, "Error loading database: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
ex.printStackTrace(); ex.printStackTrace();
@ -664,6 +728,7 @@ public class KeepassApp extends JFrame {
treeModel.setRoot(new DefaultMutableTreeNode("Database locked")); treeModel.setRoot(new DefaultMutableTreeNode("Database locked"));
statusLabel.setText(" Database locked."); statusLabel.setText(" Database locked.");
updateMenuState();
// Re-open password prompt // Re-open password prompt
if (currentFile != null) { if (currentFile != null) {
@ -686,6 +751,7 @@ public class KeepassApp extends JFrame {
updateEntryFromDialog(entry, dialog); updateEntryFromDialog(entry, dialog);
displayEntriesInGroup(currentGroup); displayEntriesInGroup(currentGroup);
statusLabel.setText(" Entry added. Remember to Save."); statusLabel.setText(" Entry added. Remember to Save.");
updateMenuState();
} }
} }
@ -699,6 +765,7 @@ public class KeepassApp extends JFrame {
updateEntryFromDialog(entry, dialog); updateEntryFromDialog(entry, dialog);
displayEntriesInGroup(currentGroup); displayEntriesInGroup(currentGroup);
statusLabel.setText(" Entry updated. Remember to Save."); statusLabel.setText(" Entry updated. Remember to Save.");
updateMenuState();
} }
} else { } else {
JOptionPane.showMessageDialog(this, "Please select an entry to edit.", "Warning", JOptionPane.WARNING_MESSAGE); JOptionPane.showMessageDialog(this, "Please select an entry to edit.", "Warning", JOptionPane.WARNING_MESSAGE);
@ -715,6 +782,7 @@ public class KeepassApp extends JFrame {
currentGroup.removeEntry(entry); currentGroup.removeEntry(entry);
displayEntriesInGroup(currentGroup); displayEntriesInGroup(currentGroup);
statusLabel.setText(" Entry deleted. Remember to Save."); statusLabel.setText(" Entry deleted. Remember to Save.");
updateMenuState();
} }
} else { } else {
JOptionPane.showMessageDialog(this, "Please select an entry to delete.", "Warning", JOptionPane.WARNING_MESSAGE); JOptionPane.showMessageDialog(this, "Please select an entry to delete.", "Warning", JOptionPane.WARNING_MESSAGE);
@ -735,6 +803,7 @@ public class KeepassApp extends JFrame {
parentGroup.addGroup(database.newGroup(name.trim())); parentGroup.addGroup(database.newGroup(name.trim()));
updateTree(database.getRootGroup()); updateTree(database.getRootGroup());
statusLabel.setText(" Category added. Remember to Save."); statusLabel.setText(" Category added. Remember to Save.");
updateMenuState();
} }
} }
@ -770,6 +839,7 @@ public class KeepassApp extends JFrame {
parentGroup.removeGroup(group); parentGroup.removeGroup(group);
updateTree(database.getRootGroup()); updateTree(database.getRootGroup());
statusLabel.setText(" Category deleted. Remember to Save."); statusLabel.setText(" Category deleted. Remember to Save.");
updateMenuState();
} }
} }