Skip to content

Commit

Permalink
Merge pull request #8164 from mbien/keep-editor-tab-order
Browse files Browse the repository at this point in the history
Persist tab order on per-project basis between close/open.
  • Loading branch information
mbien authored Jan 19, 2025
2 parents 5241929 + 6225b37 commit 235b99a
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1236,7 +1236,7 @@ static void shutdown() {
//a bit on magic here. We want to do the goup document persistence before notifyClosed in hope of the
// ant projects saving their project data before being closed. (ant ptojects call saveProjct() in the openclose hook.
// the caller of this method calls saveAllProjectt() later.
Group.onShutdown(new HashSet<Project>(INSTANCE.openProjects));
Group.onShutdown(new LinkedHashSet<>(INSTANCE.openProjects));
for (Project p : INSTANCE.openProjects) {
notifyClosed(p);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@
import java.awt.event.ActionEvent;
import java.io.CharConversionException;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -112,21 +113,21 @@ public boolean open (FileObject fo) {
public Map<Project,Set<String>> close(final Project[] projects,
final boolean notifyUI) {
final Wrapper wr = new Wrapper();
wr.urls4project = new HashMap<Project,Set<String>>();
wr.urls4project = new LinkedHashMap<>();
doClose(projects, notifyUI, wr);
return wr.urls4project;
}

private void doClose(Project[] projects, boolean notifyUI, Wrapper wr) {
List<Project> listOfProjects = Arrays.asList(projects);
for (Project p : listOfProjects) { //#232668 all projects need an entry in the map - to handle projects without files correctly
wr.urls4project.put(p, new LinkedHashSet<String>());
wr.urls4project.put(p, new LinkedHashSet<>());
}
Set<DataObject> openFiles = new HashSet<DataObject>();
final Set<TopComponent> tc2close = new HashSet<TopComponent>();
Set<DataObject> openFiles = new LinkedHashSet<>();
List<TopComponent> tc2close = new ArrayList<>();

ERR.finer("Closing TCs");
final Set<TopComponent> openedTC = getOpenedTCs();
List<TopComponent> openedTC = getOpenedTCs();

for (TopComponent tc : openedTC) {
DataObject dobj = tc.getLookup().lookup(DataObject.class);
Expand Down Expand Up @@ -193,28 +194,25 @@ public void run() {
}
}

private Set<TopComponent> getOpenedTCs() {
final Set<TopComponent> openedTC = new HashSet<TopComponent>();
Runnable r = new Runnable() {
public void run() {
WindowManager wm = WindowManager.getDefault();
for (Mode mode : wm.getModes()) {
//#84546 - this condituon should allow us to close just editor related TCs that are in any imaginable mode.
if (!wm.isEditorMode(mode)) {
continue;
}
ERR.log(Level.FINER, "Closing TCs in mode {0}", mode.getName());
openedTC.addAll(Arrays.asList(wm.getOpenedTopComponents(mode)));
private List<TopComponent> getOpenedTCs() {
List<TopComponent> openedTC = new ArrayList<>();
Runnable onEDT = () -> {
WindowManager wm = WindowManager.getDefault();
for (Mode mode : wm.getModes()) {
//#84546 - this condituon should allow us to close just editor related TCs that are in any imaginable mode.
if (!wm.isEditorMode(mode)) {
continue;
}
ERR.log(Level.FINER, "Closing TCs in mode {0}", mode.getName());
openedTC.addAll(Arrays.asList(wm.getOpenedTopComponents(mode)));
}
};
if (SwingUtilities.isEventDispatchThread()) {
r.run();
onEDT.run();
} else {
try {
SwingUtilities.invokeAndWait(r);
}
catch (Exception ex) {
SwingUtilities.invokeAndWait(onEDT);
} catch (InterruptedException | InvocationTargetException ex) {
Exceptions.printStackTrace(ex);
}
}
Expand Down Expand Up @@ -483,35 +481,22 @@ public static boolean closeAllDocuments(Project[] projects, boolean notifyUI, St
// store project's documents
// loop all project being closed
for (Map.Entry<Project,Set<String>> entry : urls4project.entrySet()) {
storeProjectOpenFiles(entry.getKey(), entry.getValue(), groupName);
storeProjectOpenFiles(entry.getKey(), new ArrayList<>(entry.getValue()), groupName);
}
}

return urls4project != null;
}

public static void storeProjectOpenFiles(Project p, Set<String> urls, String groupName) {
AuxiliaryConfiguration aux = ProjectUtils.getAuxiliaryConfiguration(p);

Set<String> openFileUrls = getOpenFilesUrls(p, groupName);
if(urls.isEmpty() && openFileUrls.isEmpty()) {
// was empty, stays empty, leave
return;
}
if(urls.size() == openFileUrls.size()) {
boolean same = true;
for (String url : openFileUrls) {
if(!urls.contains(url)) {
same = false;
break;
}
}
if(same) {
// nothing changed, leave
return;
}
public static void storeProjectOpenFiles(Project p, List<String> urls, String groupName) {

List<String> openFileUrls = getOpenFilesUrls(p, groupName);
// check if file list changed, order matters
if (urls.equals(openFileUrls)) {
return;
}


AuxiliaryConfiguration aux = ProjectUtils.getAuxiliaryConfiguration(p);
aux.removeConfigurationFragment (OPEN_FILES_ELEMENT, OPEN_FILES_NS, false);

Element openFiles = aux.getConfigurationFragment(OPEN_FILES_ELEMENT, OPEN_FILES_NS2, false);
Expand Down Expand Up @@ -558,8 +543,8 @@ public static Set<FileObject> openProjectFiles (Project p, Group grp) {
String groupName = grp == null ? null : grp.getName();
ERR.log(Level.FINE, "Trying to open files from {0}...", p);

Set<String> urls = getOpenFilesUrls(p, groupName);
Set<FileObject> toRet = new HashSet<FileObject>();
List<String> urls = getOpenFilesUrls(p, groupName);
Set<FileObject> toRet = new LinkedHashSet<>();
for (String url : urls) {
ERR.log(Level.FINE, "Will try to open {0}", url);
FileObject fo;
Expand Down Expand Up @@ -598,12 +583,13 @@ public static Set<FileObject> openProjectFiles (Project p, Group grp) {
return toRet;
}

private static Set<String> getOpenFilesUrls(Project p, String groupName) {
/// Returns an deduplicated list of opened file URLs in encounter order for this project and group.
private static List<String> getOpenFilesUrls(Project p, String groupName) {
AuxiliaryConfiguration aux = ProjectUtils.getAuxiliaryConfiguration(p);

Element openFiles = aux.getConfigurationFragment (OPEN_FILES_ELEMENT, OPEN_FILES_NS2, false);
if (openFiles == null) {
return Collections.emptySet();
return Collections.emptyList();
}

Element groupEl = null;
Expand All @@ -619,16 +605,16 @@ private static Set<String> getOpenFilesUrls(Project p, String groupName) {
}

if (groupEl == null) {
return Collections.emptySet();
return Collections.emptyList();
}

NodeList list = groupEl.getElementsByTagNameNS(OPEN_FILES_NS2, FILE_ELEMENT);
Set<String> toRet = new HashSet<String>();
Set<String> set = new LinkedHashSet<>();
for (int i = 0; i < list.getLength (); i++) {
String url = list.item (i).getChildNodes ().item (0).getNodeValue ();
toRet.add(url);
String url = list.item(i).getChildNodes().item(0).getNodeValue();
set.add(url);
}
return toRet;
return new ArrayList<>(set);
}

// interface for handling project's documents stored in project private.xml
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -326,7 +326,7 @@ protected static String sanitizeNameAndUniquifyForId(String name) {
public static void onShutdown(Set<Project> prjs) {
Group active = getActiveGroup();
String oldGroupName = active != null ? active.getName() : null;
Set<Project> stayOpened = new HashSet<Project>(prjs);
Set<Project> stayOpened = new LinkedHashSet<>(prjs);
Map<Project, Set<DataObject>> documents = getOpenedDocuments(stayOpened, true);
for (Project p : stayOpened) {
Set<DataObject> oldDocuments = documents.get(p);
Expand All @@ -335,18 +335,18 @@ public static void onShutdown(Set<Project> prjs) {
}

private static void persistDocumentsInGroup(Project p, Set<DataObject> get, String oldGroupName) {
Set<String> urls = new HashSet<String>();
Set<String> urls = new LinkedHashSet<>();
if (get != null) {
for (DataObject dob : get) {
//same way of creating string as in ProjectUtilities
urls.add(dob.getPrimaryFile().toURL().toExternalForm());
}
}
ProjectUtilities.storeProjectOpenFiles(p, urls, oldGroupName);
ProjectUtilities.storeProjectOpenFiles(p, new ArrayList<>(urls), oldGroupName);
}

private static Map<Project, Set<DataObject>> getOpenedDocuments(final Set<Project> listOfProjects, boolean shutdown) {
final Map<Project, Set<DataObject>> toRet = new HashMap<Project, Set<DataObject>>();
Map<Project, Set<DataObject>> toRet = new LinkedHashMap<>();
Runnable runnable = new Runnable() {
@Override
public void run() {
Expand All @@ -364,11 +364,8 @@ public void run() {
Project owner = FileOwnerQuery.getOwner(fobj);

if (listOfProjects.contains(owner)) {
if (!toRet.containsKey(owner)) {
// add project
toRet.put(owner, new LinkedHashSet<DataObject>());
}
toRet.get(owner).add(dobj);
toRet.computeIfAbsent(owner, k -> new LinkedHashSet<>())
.add(dobj); // add project
}
}
}
Expand All @@ -379,9 +376,7 @@ public void run() {
assert !SwingUtilities.isEventDispatchThread();
try {
SwingUtilities.invokeAndWait(runnable);
} catch (InterruptedException ex) {
Exceptions.printStackTrace(ex);
} catch (InvocationTargetException ex) {
} catch (InterruptedException | InvocationTargetException ex) {
Exceptions.printStackTrace(ex);
}
} else {
Expand Down

0 comments on commit 235b99a

Please sign in to comment.