diff --git a/CHANGELOG.md b/CHANGELOG.md
index 35569262..2690be35 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,4 @@
+- Added alphabetical sorting to the "Select Project" dropdown (https://github.com/nbclaudecodegui/NetbeansClaudeCodeGui/issues/21)
- Fixed Default profile settings (API key, connection type, proxy, etc.) not being saved when edited in Tools → Options → Claude Code → Profiles
- Fixed MCP config not working on Windows due to quote stripping in CreateProcess (https://github.com/nbclaudecodegui/NetbeansClaudeCodeGui/issues/13)
- Improved error panel on process start failure: shows Working Directory and CLAUDE_CONFIG_DIR fields (before Command and Error) for easier diagnosis; all fields have a right-click Copy menu; fixed "Restart Advanced…" not dismissing the error panel
diff --git a/pom.xml b/pom.xml
index 76c0ac7c..69c8dd62 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
io.github.nbclaudecodegui
netbeans-claude-code-gui
- 0.21.40-SNAPSHOT
+ 0.21.41-SNAPSHOT
nbm
Netbeans Claude Code GUI
NetBeans plugin that provides a GUI for Claude Code CLI — run claude code sessions directly inside the IDE.
diff --git a/src/main/java/io/github/nbclaudecodegui/ui/ClaudeSessionSelectorPanel.java b/src/main/java/io/github/nbclaudecodegui/ui/ClaudeSessionSelectorPanel.java
index 2653cc81..6de68d64 100644
--- a/src/main/java/io/github/nbclaudecodegui/ui/ClaudeSessionSelectorPanel.java
+++ b/src/main/java/io/github/nbclaudecodegui/ui/ClaudeSessionSelectorPanel.java
@@ -13,6 +13,8 @@
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
import java.util.List;
import java.util.logging.Logger;
import java.util.prefs.Preferences;
@@ -494,7 +496,13 @@ private void populateProjectCombo() {
DefaultComboBoxModel cbModel = new DefaultComboBoxModel<>();
cbModel.addElement(new ProjectItem(null,
NbBundle.getMessage(ClaudeSessionSelectorPanel.class, "LBL_SelectProject")));
- for (Project p : OpenProjects.getDefault().getOpenProjects()) {
+ // Sort projects alphabetically (case-insensitive) so the user can find
+ // their project quickly regardless of the order NetBeans returns them.
+ Project[] projects = OpenProjects.getDefault().getOpenProjects();
+ Arrays.sort(projects, Comparator.comparing(
+ p -> ProjectUtils.getInformation(p).getDisplayName(),
+ String.CASE_INSENSITIVE_ORDER));
+ for (Project p : projects) {
cbModel.addElement(new ProjectItem(p,
ProjectUtils.getInformation(p).getDisplayName()));
}
diff --git a/src/test/java/io/github/nbclaudecodegui/ui/ClaudeSessionSelectorPanelTest.java b/src/test/java/io/github/nbclaudecodegui/ui/ClaudeSessionSelectorPanelTest.java
index 0f723191..fff5ec92 100644
--- a/src/test/java/io/github/nbclaudecodegui/ui/ClaudeSessionSelectorPanelTest.java
+++ b/src/test/java/io/github/nbclaudecodegui/ui/ClaudeSessionSelectorPanelTest.java
@@ -3,6 +3,8 @@
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
+import java.util.Arrays;
+import java.util.Comparator;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
@@ -157,6 +159,36 @@ void resolveTabLabelNonProjectDirReturnsFallback() throws IOException {
}
}
+ // -------------------------------------------------------------------------
+ // Project combo sorting (issue #21)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Verifies that the comparator used in {@code populateProjectCombo()} sorts
+ * project names case-insensitively. The test stands in for the full UI
+ * flow (which requires a live NetBeans module system) and confirms that
+ * the sorting algorithm itself is correct.
+ */
+ @Test
+ void projectComboSortIsCaseInsensitive() {
+ String[] names = {"Zebra", "apple", "Banana", "cherry"};
+ Arrays.sort(names, Comparator.comparing(s -> s, String.CASE_INSENSITIVE_ORDER));
+ assertArrayEquals(new String[]{"apple", "Banana", "cherry", "Zebra"}, names,
+ "Projects must be sorted alphabetically, case-insensitive");
+ }
+
+ @Test
+ void projectComboSortIsStableForEqualCaseNames() {
+ String[] names = {"Beta", "alpha", "ALPHA", "beta"};
+ Arrays.sort(names, Comparator.comparing(s -> s, String.CASE_INSENSITIVE_ORDER));
+ // All alpha-variants before beta-variants; relative order within a group
+ // is preserved (Arrays.sort is stable).
+ assertEquals("alpha", names[0].toLowerCase(),
+ "First group must be 'alpha' variants");
+ assertEquals("beta", names[2].toLowerCase(),
+ "Second group must be 'beta' variants");
+ }
+
// -------------------------------------------------------------------------
// History persistence helpers
// -------------------------------------------------------------------------