diff --git a/ide/git/nbproject/project.properties b/ide/git/nbproject/project.properties index f546c5f6b429..a3fbf1012c3d 100644 --- a/ide/git/nbproject/project.properties +++ b/ide/git/nbproject/project.properties @@ -15,7 +15,7 @@ # specific language governing permissions and limitations # under the License. javac.compilerargs=-Xlint -javac.release=17 +javac.release=21 nbm.homepage=http://netbeans.org/projects/versioncontrol/pages/Git_main nbm.module.author=Ondrej Vrabec nbm.needs.restart=true diff --git a/ide/git/src/org/netbeans/modules/git/FileStatusCache.java b/ide/git/src/org/netbeans/modules/git/FileStatusCache.java index 011f0983bd2e..c333fccbc4c0 100644 --- a/ide/git/src/org/netbeans/modules/git/FileStatusCache.java +++ b/ide/git/src/org/netbeans/modules/git/FileStatusCache.java @@ -57,6 +57,7 @@ public class FileStatusCache { public static final String PROP_FILE_STATUS_CHANGED = "status.changed"; // NOI18N + public static final String PROP_FILES_STATUS_CHANGED = "status.changed.batch"; // NOI18N private final CacheIndex conflictedFiles, modifiedFiles, ignoredFiles; private static final Logger LOG = Logger.getLogger("org.netbeans.modules.git.status.cache"); //NOI18N @@ -562,6 +563,7 @@ private void refreshStatusesBatch (Map interestingFiles) { boolean fireEvent = true; current = getInfo(file); fi = checkForIgnore(fi, current, file); + boolean upToDateOnFirstLoad = current == null && fi.getStatus().equals(EnumSet.of(Status.UPTODATE)); if (equivalent(fi, current)) { // no need to fire an event if (Utilities.isWindows() || Utilities.isMac()) { @@ -570,6 +572,10 @@ private void refreshStatusesBatch (Map interestingFiles) { } else { continue; } + } else if (upToDateOnFirstLoad) { + // file is up-to-date and not yet in cache: UPTODATE is the implicit default, + // no cache update or event needed + continue; } boolean addToIndex = updateCachedValue(fi, file); indexUpdates.add(new IndexUpdateItem(file, fi, addToIndex)); @@ -579,8 +585,8 @@ private void refreshStatusesBatch (Map interestingFiles) { } updateIndexBatch(indexUpdates); } - for (ChangedEvent event : events) { - fireFileStatusChanged(event); + if (!events.isEmpty()) { + listenerSupport.firePropertyChange(PROP_FILES_STATUS_CHANGED, null, events); } } diff --git a/ide/git/src/org/netbeans/modules/git/GitVCS.java b/ide/git/src/org/netbeans/modules/git/GitVCS.java index c8951d42c32a..d5ff165c2413 100644 --- a/ide/git/src/org/netbeans/modules/git/GitVCS.java +++ b/ide/git/src/org/netbeans/modules/git/GitVCS.java @@ -23,6 +23,8 @@ import java.beans.PropertyChangeListener; import java.util.MissingResourceException; import java.io.File; +import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.logging.Logger; import java.util.prefs.PreferenceChangeEvent; @@ -38,9 +40,9 @@ * @author ondra */ @VersioningSystem.Registration( - displayName="#CTL_Git_DisplayName", - menuLabel="#CTL_Git_MainMenu", - metadataFolderNames={".git"}, + displayName="#CTL_Git_DisplayName", + menuLabel="#CTL_Git_MainMenu", + metadataFolderNames={".git"}, actionsCategory="Git" ) public class GitVCS extends VersioningSystem implements PropertyChangeListener, PreferenceChangeListener { @@ -48,7 +50,7 @@ public class GitVCS extends VersioningSystem implements PropertyChangeListener, private static final Logger LOG = Logger.getLogger("org.netbeans.modules.git.GitVCS"); //NOI18N public GitVCS() { - putProperty(PROP_DISPLAY_NAME, getDisplayName()); + putProperty(PROP_DISPLAY_NAME, getDisplayName()); putProperty(PROP_MENU_LABEL, org.openide.util.NbBundle.getMessage(GitVCS.class, "CTL_Git_MainMenu")); // NOI18N GitModuleConfig.getDefault().getPreferences().addPreferenceChangeListener(this); Git.getInstance().registerGitVCS(this); @@ -77,7 +79,7 @@ public void getOriginalFile (File workingCopy, File originalFile) { public File getTopmostManagedAncestor(File file) { return Git.getInstance().getTopmostManagedAncestor(file); } - + @Override public CollocationQueryImplementation getCollocationQueryImplementation() { return collocationQueryImplementation; @@ -111,6 +113,13 @@ public void propertyChange(PropertyChangeEvent event) { if (event.getPropertyName().equals(FileStatusCache.PROP_FILE_STATUS_CHANGED)) { FileStatusCache.ChangedEvent changedEvent = (FileStatusCache.ChangedEvent) event.getNewValue(); fireStatusChanged(changedEvent.getFile()); + } else if (event.getPropertyName().equals(FileStatusCache.PROP_FILES_STATUS_CHANGED)) { + List changedEvents = (List) event.getNewValue(); + Set files = HashSet.newHashSet(changedEvents.size()); + for (FileStatusCache.ChangedEvent e : changedEvents) { + files.add(e.getFile()); + } + fireStatusChanged(files); } else if (event.getPropertyName().equals(Git.PROP_ANNOTATIONS_CHANGED)) { fireAnnotationsChanged((Set) event.getNewValue()); } else if (event.getPropertyName().equals(Git.PROP_VERSIONED_FILES_CHANGED)) { diff --git a/ide/git/src/org/netbeans/modules/git/ui/diff/MultiDiffPanelController.java b/ide/git/src/org/netbeans/modules/git/ui/diff/MultiDiffPanelController.java index 6ff1626e0f41..2d6f978bb57a 100644 --- a/ide/git/src/org/netbeans/modules/git/ui/diff/MultiDiffPanelController.java +++ b/ide/git/src/org/netbeans/modules/git/ui/diff/MultiDiffPanelController.java @@ -196,7 +196,7 @@ public class MultiDiffPanelController implements ActionListener, PropertyChangeL private GitProgressSupport statusRefreshSupport; private PreferenceChangeListener prefList; - + private final Revision revisionOriginalLeft; private final Revision revisionOriginalRight; private Revision revisionLeft; @@ -211,7 +211,7 @@ public class MultiDiffPanelController implements ActionListener, PropertyChangeL private int popupViewIndex; private int requestedRightLine = -1; private int requestedLeftLine = -1; - + private static final int VIEW_MODE_TABLE = 1; private static final int VIEW_MODE_TREE = 2; private int currentSetupDiffLengthChanged; @@ -270,7 +270,7 @@ public MultiDiffPanelController (File file, Revision rev1, Revision rev2, int re prepareTask = RP.create(dpt); prepareTask.schedule(0); } - + private MultiDiffPanelController (VCSContext context, Revision revisionLeft, Revision revisionRight, boolean fixedRevisions) { this.context = context; this.revisionLeft = revisionOriginalLeft = revisionLeft; @@ -315,7 +315,7 @@ private void setActiveComponent (DiffFileViewComponent fileComponent) panel.splitPane.setTopComponent(getActiveFileComponent().getComponent()); panel.splitPane.setDividerLocation(gg); } - + private void refreshSelectionCombos () { if (!fixedRevisions && GitUtils.getRepositoryRoots(context).size() == 1) { panel.cmbDiffTreeFirst.setEnabled(false); @@ -432,7 +432,7 @@ public void componentClosed () { cancelBackgroundTasks(); setups.clear(); editorCookies.clear(); - + if (list != null) { Git.getInstance().getFileStatusCache().removePropertyChangeListener(list); } @@ -569,7 +569,7 @@ private void initToolbarButtons () { panel.treeButton.setVisible(false); } } - + private JComponent getInfoPanelLoading () { if (infoPanelLoadingFromRepo == null) { infoPanelLoadingFromRepo = new NoContentPanel(NbBundle.getMessage(MultiDiffPanel.class, "MSG_DiffPanel_NoContent")); @@ -812,11 +812,11 @@ public void run () { public void run () { multiTextDiffSupport = null; } - + }); } } - + private String findEncoding () { for (File f : actionRoots.getValue()) { FileObject fo = FileUtil.toFileObject(f); @@ -861,7 +861,7 @@ private void exportDiff (ByteArrayOutputStream bos) throws GitException { actionRoots.getKey(), Bundle.MSG_DiffPanel_multiTextualDiff_preparing()); } } - + }); displayDiffView(); } @@ -891,7 +891,7 @@ private Map.Entry getSelectedActionRoots () { ctx = GitUtils.getContextForFiles(filterExcluded(selectedFiles)); return GitUtils.getActionRoots(ctx); } - + private File[] filterExcluded (File[] files) { List filtered = new ArrayList<>(files.length); for (File f : files) { @@ -903,7 +903,7 @@ private File[] filterExcluded (File[] files) { } return filtered.toArray(new File[0]); } - + private boolean showingFileComponent() { return getActiveFileComponent() != null; } @@ -1064,7 +1064,7 @@ private DiffMode getDiffMode () { } return diffMode; } - + private Revision getSelectedRevision (JComboBox cmbDiffTree) { Object selectedItem = cmbDiffTree.getSelectedItem(); Revision selection = null; @@ -1123,15 +1123,25 @@ public void propertyChange (PropertyChangeEvent evt) { if (FileStatusCache.PROP_FILE_STATUS_CHANGED.equals(evt.getPropertyName())) { FileStatusCache.ChangedEvent changedEvent = (FileStatusCache.ChangedEvent) evt.getNewValue(); if (LOG.isLoggable(Level.FINE)) { - LOG.log(Level.FINE, "File status for file {0} changed from {1} to {2}", new Object[] { - changedEvent.getFile(), + LOG.log(Level.FINE, "File status for file {0} changed from {1} to {2}", new Object[] { + changedEvent.getFile(), changedEvent.getOldInfo(), changedEvent.getNewInfo() } ); } - if (revisionLeft == Revision.HEAD // remove when we're able to refresh single file changes for Local vs. any revision + if (revisionLeft == Revision.HEAD // remove when we're able to refresh single file changes for Local vs. any revision && revisionRight == Revision.LOCAL && affectsView(changedEvent)) { applyChange(changedEvent); } + } else if (FileStatusCache.PROP_FILES_STATUS_CHANGED.equals(evt.getPropertyName())) { + if (revisionLeft == Revision.HEAD && revisionRight == Revision.LOCAL) { + @SuppressWarnings("unchecked") + List changedEvents = (List) evt.getNewValue(); + for (FileStatusCache.ChangedEvent changedEvent : changedEvents) { + if (affectsView(changedEvent)) { + applyChange(changedEvent); + } + } + } } else if (DiffController.PROP_DIFFERENCES.equals(evt.getPropertyName())) { // something has changed Setup setup = currentSetup; @@ -1537,7 +1547,7 @@ private boolean isLocal () { * Eliminates unnecessary cache.listFiles call as well as the whole node creation process () */ private final class ApplyChangesTask implements Runnable, Cancellable { - + private volatile boolean canceled; @Override @@ -1651,7 +1661,7 @@ public boolean cancel () { return true; } } - + private class RefreshComboTask implements Runnable { @Override @@ -1663,7 +1673,7 @@ public void run () { if (revisionOriginalLeft != Revision.HEAD) { modelLeft.add(Revision.HEAD); } - modelRight.add(revisionOriginalRight); + modelRight.add(revisionOriginalRight); if (revisionOriginalRight != Revision.LOCAL) { modelRight.add(Revision.LOCAL); } @@ -1767,7 +1777,7 @@ public void run() { GitClientExceptionHandler.notifyException(exception, true); } } - + private DiffNode[] prepareSetupsToRefresh () { return Mutex.EVENT.readAccess(new Mutex.Action() { @Override @@ -1810,7 +1820,7 @@ private int getMatchingLine (StreamSource ss2, StreamSource ss1, int requestedRi } } }// - + @NbBundle.Messages({ "MSG_Revision_Select_Tooltip=Select a revision from the picker" }) diff --git a/ide/git/src/org/netbeans/modules/git/ui/status/VersioningPanelController.java b/ide/git/src/org/netbeans/modules/git/ui/status/VersioningPanelController.java index 2a0ed8d38079..5fd2266740c5 100644 --- a/ide/git/src/org/netbeans/modules/git/ui/status/VersioningPanelController.java +++ b/ide/git/src/org/netbeans/modules/git/ui/status/VersioningPanelController.java @@ -408,6 +408,14 @@ public void propertyChange (PropertyChangeEvent evt) { if (affectsView((FileStatusCache.ChangedEvent) evt.getNewValue())) { applyChange(changedEvent); } + } else if (FileStatusCache.PROP_FILES_STATUS_CHANGED.equals(evt.getPropertyName())) { + @SuppressWarnings("unchecked") + List changedEvents = (List) evt.getNewValue(); + for (FileStatusCache.ChangedEvent changedEvent : changedEvents) { + if (affectsView(changedEvent)) { + applyChange(changedEvent); + } + } } } diff --git a/ide/versioning.core/src/org/netbeans/modules/versioning/core/VersioningAnnotationProvider.java b/ide/versioning.core/src/org/netbeans/modules/versioning/core/VersioningAnnotationProvider.java index 69eb1ebe538f..d9c3983897c1 100644 --- a/ide/versioning.core/src/org/netbeans/modules/versioning/core/VersioningAnnotationProvider.java +++ b/ide/versioning.core/src/org/netbeans/modules/versioning/core/VersioningAnnotationProvider.java @@ -47,13 +47,13 @@ /** * Plugs into IDE filesystem and delegates annotation work to registered versioning systems. - * + * * @author Maros Sandor */ public class VersioningAnnotationProvider { - + private static final VersioningAnnotationProvider instance = new VersioningAnnotationProvider(); - + private static final Logger LOG = Logger.getLogger(VersioningAnnotationProvider.class.getName()); private static final int CACHE_INITIAL_SIZE = 500; private static final long CACHE_ITEM_MAX_AGE = getMaxAge(); @@ -62,11 +62,11 @@ public class VersioningAnnotationProvider { private VersioningAnnotationProvider() { } - + public static VersioningAnnotationProvider getDefault() { return instance; } - + private VersioningSystem getOwner(VCSFileProxy file, Boolean isFile) { return file == null ? null : VersioningManager.getInstance().getOwner(file, isFile); } @@ -101,7 +101,7 @@ public Action[] actions(Set files) { SystemAction.get(InitLHSystemAction.class) }; } - + List actions = new ArrayList<>(); LocalHistoryActions localHistoryAction = null; @@ -136,8 +136,8 @@ public Action[] actions(Set files) { vs = owners.keySet().iterator().next(); } else { return actions.toArray(Action[]::new); - } - + } + VCSAnnotator an = null; if (vs != null) { an = vs.getVCSAnnotator(); @@ -150,13 +150,13 @@ public Action[] actions(Set files) { return actions.toArray(Action[]::new); } - + public static class VersioningSystemActions extends AbstractVersioningSystemActions { } public static class LocalHistoryActions extends AbstractVersioningSystemActions { } - + public static class InitLHSystemAction extends InitVersioningSystemAction { public InitLHSystemAction() { super(); @@ -166,7 +166,7 @@ public String getName() { return NbBundle.getMessage(VersioningAnnotationProvider.class, "CTL_MenuItem_LocalHistory"); } } - + public static class InitVersioningSystemAction extends SystemAction implements Presenter.Popup { @Override @@ -184,9 +184,9 @@ public HelpCtx getHelpCtx() { return null; } } - + public abstract static class AbstractVersioningSystemActions extends SystemAction implements ContextAwareAction { - + private VersioningSystem system; @Override @@ -213,7 +213,7 @@ public void setVersioningSystem(VersioningSystem system) { this.system = system; } } - + private static class RealVersioningSystemActions extends AbstractAction implements Presenter.Popup { private final VersioningSystem system; @@ -234,10 +234,10 @@ public void actionPerformed(ActionEvent e) { public JMenuItem getPopupPresenter() { return new VersioningSystemMenuItem(); } - + @NbBundle.Messages("LBL_PopupMenu_Initializing=Initializing...") private class VersioningSystemMenuItem extends JMenu { - + private boolean popupContructed; public VersioningSystemMenuItem() { @@ -284,7 +284,7 @@ static void refreshAllAnnotations() { instance.refreshAnnotations(null); } } - + /** * Refreshes annotations for all given files and all parent folders of those files. * @@ -295,77 +295,83 @@ void refreshAnnotations(Set files) { } void refreshAnnotations(Set files, boolean removeFromCache) { - if (files == null) { + + if (files == null) { LOG.log(Level.FINE, "refreshing all annotations"); //NOI18N refreshAllAnnotationsTask.schedule(2000); return; } - - if (removeFromCache) { - LOG.log(Level.FINE, "refreshing annotations for {0}", files); //NOI18N - if (LOG.isLoggable(Level.FINEST)) { - LOG.log(Level.FINEST, "refreshing annotations called from:", new Exception()); //NOI18N - } - } - - for (VCSFileProxy file : files) { - // try to limit the number of normalizeFile calls: - // let's find the closest existent FO, then list it's parents with FileObject.getParent(); - FileObject fo = file.toFileObject(); - if (fo == null) { - fo = getExistingParent(file); - } else { - // file exists, plan it to refresh - addToMap(filesToRefresh, fo, removeFromCache); - fo = fo.getParent(); - } + + final RequestProcessor.Task refreshAnnotationsTask = rp.create(() -> { if (removeFromCache) { - // fo is the closest existing parent - for (FileObject parent = fo; parent != null; parent = parent.getParent()) { - // plan parent to refresh - addToMap(parentsToRefresh, parent, removeFromCache); + LOG.log(Level.FINE, "refreshing annotations for {0}", files); //NOI18N + if (LOG.isLoggable(Level.FINEST)) { + LOG.log(Level.FINEST, "refreshing annotations called from:", new Exception()); //NOI18N } } - } - - fireFileStatusChangedTask.schedule(2000); + + for (VCSFileProxy file : files) { + // try to limit the number of normalizeFile calls: + // let's find the closest existent FO, then list it's parents with FileObject.getParent(); + FileObject fo = file.toFileObject(); + if (fo == null) { + fo = getExistingParent(file); + } else { + // file exists, plan it to refresh + addToMap(filesToRefresh, fo, removeFromCache); + fo = fo.getParent(); + } + + if (removeFromCache) { + // fo is the closest existing parent + for (FileObject parent = fo; parent != null; parent = parent.getParent()) { + // plan parent to refresh + addToMap(parentsToRefresh, parent, removeFromCache); + } + } + } + + fireFileStatusChangedTask.schedule(2000); + }); + + refreshAnnotationsTask.schedule(0); } - + /** - * Stores all files which have to be refreshed + * Stores all files which have to be refreshed */ private final Map> filesToRefresh = new HashMap<>(); - + /** - * Stores all parents from files which have to be refreshed + * Stores all parents from files which have to be refreshed */ private final Map> parentsToRefresh = new HashMap<>(); - + private RequestProcessor rp = new RequestProcessor("Versioning fire FileStatusChanged", 1, true); - + /** * Refreshes all annotations and clears the maps holding all files and their parents which have to be refreshed */ - private RequestProcessor.Task refreshAllAnnotationsTask = rp.create(new Runnable() { + private RequestProcessor.Task refreshAllAnnotationsTask = rp.create(new Runnable() { @Override - public void run() { + public void run() { clearMap(filesToRefresh); clearMap(parentsToRefresh); labelCache.removeAll(); iconCache.removeAll(); - + VersioningManager.deliverStatusEvent(new VCSAnnotationEvent(true, true)); } - }); - + }); + /** * Refreshes all files stored in filesToRefresh and parentsToRefresh - */ + */ private RequestProcessor.Task fireFileStatusChangedTask = rp.create(new Runnable() { @Override public void run() { - + // createInitializingMenu and fire for all files which have to be refreshed List fileEvents = new ArrayList<>(); List folderEvents = new ArrayList<>(); @@ -384,7 +390,7 @@ public void run() { } else { files.add(fo); } - } + } set.clear(); e.setValue(new HashSet<>()); if(!files.isEmpty()) { @@ -393,33 +399,33 @@ public void run() { if(!folders.isEmpty()) { folderEvents.add(new VCSAnnotationEvent(folders, true, true)); } - } - } + } + } fireFileStatusEvents(fileEvents); fireFileStatusEvents(folderEvents); // createInitializingMenu and fire events for all parent from each file which has to be refreshed - List parentEvents = new ArrayList<>(); + List parentEvents = new ArrayList<>(); synchronized(parentsToRefresh) { for (Map.Entry> e : parentsToRefresh.entrySet()) { Set set = e.getValue(); Set files = new HashSet<>(set); parentEvents.add(new VCSAnnotationEvent(files, true, false)); - e.setValue(new HashSet<>()); + e.setValue(new HashSet<>()); set.clear(); } } fireFileStatusEvents(parentEvents); } - + private void fireFileStatusEvents(Collection events) { for(VCSAnnotationEvent event : events) { VersioningManager.deliverStatusEvent(event); } - } - }); - + } + }); + private void clearMap(Map> map) { synchronized(map) { if(!map.isEmpty()) { @@ -427,7 +433,7 @@ private void clearMap(Map> map) { } } } - + private void addToMap(Map> map, FileObject fo, boolean removeFromCache) { if(fo == null) { return; @@ -438,8 +444,8 @@ private void addToMap(Map> map, FileObject fo, boole } catch (FileStateInvalidException e) { // ignore files in invalid filesystems return; - } - synchronized (map) { + } + synchronized (map) { map.computeIfAbsent(fs, k -> new HashSet<>()) .add(fo); if (removeFromCache) { @@ -624,7 +630,7 @@ private T annotate(VCSAnnotator annotator, T initialValue, VCSContext context) { return null; } } - + private T annotate (T initialValue, Set files) { long ft = System.currentTimeMillis(); if (LOG.isLoggable(Level.FINEST)) { diff --git a/ide/versioning.ui/src/org/netbeans/modules/versioning/ui/diff/DiffSidebarManager.java b/ide/versioning.ui/src/org/netbeans/modules/versioning/ui/diff/DiffSidebarManager.java index ce3b35f8a464..98e67c26e364 100644 --- a/ide/versioning.ui/src/org/netbeans/modules/versioning/ui/diff/DiffSidebarManager.java +++ b/ide/versioning.ui/src/org/netbeans/modules/versioning/ui/diff/DiffSidebarManager.java @@ -45,7 +45,7 @@ /** * Central place of diff integration into editor and errorstripe. - * + * * @author Maros Sandor */ public class DiffSidebarManager implements PreferenceChangeListener, PropertyChangeListener { @@ -58,14 +58,14 @@ public class DiffSidebarManager implements PreferenceChangeListener, PropertyCha * Temporary top folder for diffsidebar in a single session */ private static File tempDir; - + /** * Request processor for long running tasks. */ private static final RequestProcessor blockingRequestProcessor = new RequestProcessor("Diffsidebar long tasks", 1, false, false); static final Logger LOG = Logger.getLogger(DiffSidebarManager.class.getName()); private static final boolean LOG_STACKTRACE = Boolean.getBoolean("versioning.diffsidebar.refresh.logstacktrace"); //NOI18N - + public static synchronized DiffSidebarManager getInstance() { if (instance == null) { instance = new DiffSidebarManager(); @@ -82,37 +82,40 @@ public static synchronized DiffSidebarManager getInstance() { private final Map sideBars = new WeakHashMap(); private DiffSidebarManager() { - sidebarEnabled = getPreferences().getBoolean(SIDEBAR_ENABLED, true); + sidebarEnabled = getPreferences().getBoolean(SIDEBAR_ENABLED, true); getPreferences().addPreferenceChangeListener(this); } public void refreshSidebars(final Set proxies) { - // pushing the change ... we may as well listen for changes in versioning manager - Set fileObjects = null; - if (proxies != null) { - fileObjects = new HashSet(proxies.size()); - for (VCSFileProxy file : proxies) { - fileObjects.add(file.toFileObject()); + + createDiffSidebarTask(() -> { + // pushing the change ... we may as well listen for changes in versioning manager + Set fileObjects = null; + if (proxies != null) { + fileObjects = new HashSet(proxies.size()); + for (VCSFileProxy file : proxies) { + fileObjects.add(file.toFileObject()); + } + fileObjects.remove(null); } - fileObjects.remove(null); - } - if (LOG_STACKTRACE && (fileObjects == null || !fileObjects.isEmpty())) { - LOG.log(Level.INFO, "Refreshing: " + fileObjects, new Exception()); - } - final Set fileObjectsToRefresh = fileObjects; - SwingUtilities.invokeLater(new Runnable() { - public void run() { - synchronized (sideBars) { - for (DiffSidebar bar : sideBars.keySet()) { - if (matches(bar, fileObjectsToRefresh)) { - bar.refresh(); + if (LOG_STACKTRACE && (fileObjects == null || !fileObjects.isEmpty())) { + LOG.log(Level.INFO, "Refreshing: " + fileObjects, new Exception()); + } + final Set fileObjectsToRefresh = fileObjects; + SwingUtilities.invokeLater(new Runnable() { + public void run() { + synchronized (sideBars) { + for (DiffSidebar bar : sideBars.keySet()) { + if (matches(bar, fileObjectsToRefresh)) { + bar.refresh(); + } } } } - } - }); + }); + }).schedule(0); } - + private boolean matches(DiffSidebar sidebar, Set fileObjects) { if (fileObjects == null) return true; for (FileObject fileObject : fileObjects) { @@ -123,10 +126,10 @@ private boolean matches(DiffSidebar sidebar, Set fileObjects) { Preferences getPreferences() { return NbPreferences.forModule(DiffSidebarManager.class); - } + } /** - * Creates a new task needed by a diff sidebar to update its structures (compute diff). - * + * Creates a new task needed by a diff sidebar to update its structures (compute diff). + * * @param runnable a runnable task * @return RP task */ @@ -155,7 +158,7 @@ private DiffSidebar getSideBar(JTextComponent target) { return null; } LOG.log(Level.FINE, "requested sidebar for {0}", file.getPath()); - + sideBar = new DiffSidebar(target, file); sideBars.put(sideBar, null); sideBar.setSidebarVisible(sidebarEnabled);