Skip to content
Merged
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 @@ -184,7 +184,7 @@ public static void setActiveGroup(Group nue, boolean isNewGroup) {
}
} else {
OpenProjectListSettings settings = OpenProjectListSettings.getInstance();
settings.setOpenProjectsURLsAsStrings(nue != null ? nue.projectPaths() : getProjectPathsByPreferences(noneGroupPref));
settings.setOpenProjectsURLsAsStrings(nue != null ? nue.projectPaths() : Collections.emptyList());

@jtulach jtulach Oct 7, 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.

Here is the new approach:

  • let --close-group not only close the group (if any)
  • but also empty the list of projects
  • if I got it right, that's exactly what @neilcsmith-net hinted here:

The --close-group option does cover some of your scenario. That might be better enforcing an empty group anyway?
@mbien wrote and Neil replied:

i use --close-group often. It starts in group none which should be empty by default.
Mine is rarely empty. As said above, I wonder whether the default for that option, and for switching to none in the UI, would be better as a clean slate.

  • Exactly! Clean state is better.
  • when @jglick introduced the project groups:
    • Jesse (probably) wanted to keep compatibility with the prior state
    • e.g. when one opts for groups and the opts out by closing them...
    • one gets to a previous state just like groups support wouldn't exists
  • that made some sense but it shows its limits these days - let's change it

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.

Yes, this is what I meant. I should make my "hints" more explicit! 😆

Ideally this should be handled in open too when projectsLoaded == true.

Interestingly, there's a TODO matching this behaviour in there already.

//TODO switching to no group always clears the opened project list.
Set<Project> newOpen = g != null ? g.getProjects(h, 10, 100) : getProjectsByPreferences(noneGroupPref, h, 10, 100);
final Set<Project> toClose = new HashSet<Project>(oldOpen);

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.

Here is an ideological justification of the behavioral change of --close-group with an outline of the future:

Group Centric View

  • Let build NetBeans projects and file view around the concept of a ProjectGroup .
  • a group is a set of projects (same as now) with few implementations AdhocGroup, DirectoryGroup, etc.)
  • there is always a single opened project group in the NetBeans IDE
    • there is a way to listen and obtain the current group
  • users can create new groups and switch between existing groups
  • the default group (none in current implementation) is switch non-persistent
    • e.g. when switching to it, it starts empty, as a fresh group
    • it keeps its project list on shutdown/restart however
  • developers can query the current group, observe its changes and get list of Project in the current group
    • there already is getActiveProjectGroup()
    • created by 6a3ae0aed18ca3e6a7af31901311ee63bd798351used only by Maven support for not clear reasons
    • let's enhance ProjectGroup with additional getters to look alike workspace and serve similar purpose
    • where workspaceFolders would be getProjects(), isTrusted(), maybe textDocuments to deal with opening previously opened editor views on group switch
  • shift the UI towards the group centric view while keeping the flexibility for expert users

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.

Agreed! With the obligatory, that discussion really belongs on dev@ 😄

created by 6a3ae0aed18ca3e6a7af31901311ee63bd798351used only by Maven support for not clear reasons

I intended to bring this up in the dev@ discussion that Groups can have different settings. Maven support can theoretically have a different Maven Home for each group configured under group properties. I think this is for that. Not sure how well we test that feature, and not that useful compared to pushing mvnw anyway.

Still, anything taking an enhanced group perspective can probably look to provide more group oriented settings available, and provide an easier UI for them.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Jesse (probably) wanted to keep compatibility with the prior state

Right. I only dimly recall, but basically the non-group was treated as a pseudo-group with its own persistent list of projects, just like the IDE prior to the introduction of the group concept.

the default group (none in current implementation) is switch non-persistent

  • e.g. when switching to it, it starts empty, as a fresh group
  • it keeps its project list on shutdown/restart however

Seems intuitive enough.

settings.setMainProjectURL(nue != null ? nue.prefs().get(KEY_MAIN, null) : null);

WindowManager.getDefault().addWindowSystemListener(new WindowSystemListener() {
Expand Down Expand Up @@ -476,6 +476,7 @@ protected static Project projectForPath(String path) {
public Set<Project> getProjects() {
return getProjects(null, 0, 0);
}

private Set<Project> getProjects(ProgressHandle h, int start, int end) {
if (h != null) {
h.progress("", start);
Expand Down Expand Up @@ -577,8 +578,7 @@ static void open(final Group g, String oldGroupName, boolean isNewGroup, Prefere
oldOpen.add(real != null ? real : open);
}

//TODO switching to no group always clears the opened project list.
Set<Project> newOpen = g != null ? g.getProjects(h, 10, 100) : getProjectsByPreferences(noneGroupPref, h, 10, 100);
Set<Project> newOpen = g != null ? g.getProjects(h, 10, 100) : Collections.emptySet();
final Set<Project> toClose = new HashSet<Project>(oldOpen);
toClose.removeAll(newOpen);
final Set<Project> toOpen = new HashSet<Project>(newOpen);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.project.ui.groups;

import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectManager;
import org.netbeans.api.project.ui.OpenProjects;
import org.netbeans.junit.MockServices;
import org.netbeans.junit.NbTestCase;
import org.netbeans.modules.project.ui.actions.TestSupport;
import org.openide.filesystems.FileUtil;

public class GroupTest extends NbTestCase {
public GroupTest(String name) {
super(name);
}

@Override
protected void setUp() throws Exception {
clearWorkDir();
MockServices.setServices(TestSupport.TestProjectFactory.class);
Group.setActiveGroup(null, false);
assertEquals("No group is active", null, OpenProjects.getDefault().getActiveProjectGroup());
}

public void testSwitchingToAgroup() {
var g = AdHocGroup.create("adHoc1", false);
Group.setActiveGroup(g, true);
var active = OpenProjects.getDefault().getActiveProjectGroup().getName();
assertEquals("Group was switched", g.getName(), active);
}

public void testSwitchingBackToNoGroupClearsOpenedProjects() throws Exception {
var root = FileUtil.toFileObject(getWorkDir());
var fo1 = TestSupport.createTestProject(root, "prj1");
var prj1 = ProjectManager.getDefault().findProject(fo1);
var fo2 = TestSupport.createTestProject(root, "prj2");
var prj2 = ProjectManager.getDefault().findProject(fo2);

OpenProjects.getDefault().open(new Project[] { prj1, prj2 }, false);

var twoOrig = OpenProjects.getDefault().openProjects().get();
assertEquals(2, twoOrig.length);
assertEquals("1st", twoOrig[0], prj1);
assertEquals("2nd", twoOrig[1], prj2);

var g = AdHocGroup.create("empty", false);
Group.setActiveGroup(g, true);
var none = OpenProjects.getDefault().openProjects().get();
assertEquals("Now there are no projects open", 0, none.length);

Group.setActiveGroup(null, false);
var backToNoGroup = OpenProjects.getDefault().openProjects().get();
assertEquals("Fresh empty group is opened", 0, backToNoGroup.length);
}

}
Loading