Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,7 @@ public final class OpenProjectList {
*/
static final Mutex MUTEX = new Mutex();

public static Comparator<Project> projectByDisplayName() {
return new ProjectByDisplayNameComparator();
}

static Comparator<? super Project> projectByPath() {
public static Comparator<? super Project> projectByPath() {
return new ProjectByPathComparator();
}

Expand Down Expand Up @@ -1926,49 +1922,6 @@ public URL getURL() {

}

private static class ProjectByDisplayNameComparator implements Comparator<Project> {

private static final Comparator<Object> COLLATOR = Collator.getInstance();

// memoize results since it could be called >1 time per project:
private final Map<Project,String> names = new HashMap<Project,String>();
private String getDisplayName(Project p) {
String n = names.get(p);
if (n == null) {
n = ProjectUtils.getInformation(p).getDisplayName();
names.put(p, n);
}
return n;
}

@Override
public int compare(Project p1, Project p2) {
// Uncoment to make the main project be the first one
// but then needs to listen to main project change
// if ( OpenProjectList.getDefault().isMainProject( p1 ) ) {
// return -1;
// }
//
// if ( OpenProjectList.getDefault().isMainProject( p2 ) ) {
// return 1;
// }

String n1 = getDisplayName(p1);
String n2 = getDisplayName(p2);
if (n1 != null && n2 != null) {
return COLLATOR.compare(n1, n2);
} else if (n1 == null && n2 != null) {
log(Level.WARNING, p1 + ": ProjectInformation.getDisplayName() should not return null!");
return -1;
} else if (n1 != null && n2 == null) {
log(Level.WARNING, p2 + ": ProjectInformation.getDisplayName() should not return null!");
return 1;
}
return 0; // both null

}

}
private static class ProjectByPathComparator implements Comparator<Project> {
@Override
public int compare(Project p1, Project p2) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ private void initValues( @NullAllowed Project p ) {
DefaultComboBoxModel projectsModel;
if (includeTemplatesWithProjects) {
Project openProjects[] = OpenProjectList.getDefault().getOpenProjects();
Arrays.sort(openProjects, OpenProjectList.projectByDisplayName());
Arrays.sort(openProjects, OpenProjectList.projectByPath());
projectsModel = new DefaultComboBoxModel( openProjects );
selectProject(p);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public class SetMainProject extends ProjectAction implements PropertyChangeListe
private static Preferences prefs() {
return NbPreferences.forModule(SetMainProject.class);
}
private static RequestProcessor RP = new RequestProcessor(SetMainProject.class);
private static final RequestProcessor RP = new RequestProcessor(SetMainProject.class);

protected JMenu subMenu;
private boolean empty;
Expand Down Expand Up @@ -162,7 +162,7 @@ public void run() {
"LBL_NoneMainProject_Name=&None"
})
private void createSubMenu(Project[] projects) {
Arrays.sort(projects, OpenProjectList.projectByDisplayName());

@jtulach jtulach Sep 21, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • while implementing b1f3e7d
  • I realized there are three places when ordering of projects is used
  • my expectation is: at all places the sorting order should be the same
  • e.g. whatever configuration option is offered, applies to all those places at once

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, let me show an annecdoctical evidence of the randomness of the sorting by display name. Sometimes I am mixing projects from multiple repositories. Today I had projects from NetBeans own code base, as well as projects from GraalVM repository open. This is how it looks like in NetBeans 31:

Randomness in old NetBeans

It is easy to recognize what projects are coming from which repository as they have different icons. But the order! Because the projects are sorted by display name, those two independent sets of projects are intermixed with each other. The ordering is random, basically.

Today I decided to switch to the latest development version and voilá:

ordering by path

The ordering by path makes sense! First of all there is a group of projects from the GraalVM repository, then there is the group of projects from the NetBeans repository. There is no nesting in the hierarchy of those groups (that'd be subject of #9624 for example), but even the grouping by path is a tremendous step forward.

PS: I've been so shocked realizing how better the ordering is! I've just had to install the (already deleted) old NetBeans again to take the picture. As it speaks for thousand of words.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, let me show an annecdoctical evidence of the randomness of the sorting by display name

I believe seeing somewhere lazy/non-blocking init mechanisms where display names were used only when available. If its there it is used, if not it falls back to something else. I an imagine - if used for sorting - it can be placed at the wrong spot initially - until the full list is refreshed.

the group-by-project dropdown of the file list behaves similarly. If it can't list all projects fast enough it will display a simple list on very first open. Once the cached, it will properly group. NB has a lot of caching behind the scenes.

image

The ordering by path makes sense!

yes I agree. I thought about this and tested that already back when I looked at #9602 (comment)

Since it sorts by String path, it should produce pretty good results. (Path.compareTo() would have been slightly more dangerous - I remember the showstopper #6361 which was hard to debug since the cause was completely removed from the symptom (that one was about weird File instances - Path may be backed by different file systems))

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seeing ... lazy/non-blocking init mechanisms where display names were used only when available.

Arrays.sort(projects, OpenProjectList.projectByPath());

// Enable disable the action according to number of open projects
if (projects.length == 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ private Node doBehaviourOfProjectsNode() throws InterruptedException {

for (Node n : view.getChildren().getNodes(true)) {
TestSupport.TestProject p = n.getLookup().lookup(TestSupport.TestProject.class);
assertNull("No project of this type, yet", p);
assertNull("No project of this type, yet: " + n, p);
}

// let project open code run
Expand Down
Loading