This is an automated email from the ASF dual-hosted git repository.

ebakke pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git


The following commit(s) were added to refs/heads/master by this push:
     new 9f212e884d Have "Close All" and friends honor "Cancel" in save prompt 
dialogs
9f212e884d is described below

commit 9f212e884d314ae221e25fcc721aaeb7dcad40c6
Author: Eirik Bakke <eba...@ultorg.com>
AuthorDate: Sat Nov 5 16:20:12 2022 -0400

    Have "Close All" and friends honor "Cancel" in save prompt dialogs
    
    When invoking "Close All" on a tab, some tabs may pop up confirmation 
dialogs asking whether their work should be saved or not. Pressing the "Cancel" 
button in any dialog, as opposed to "Save" or "Discard", should stop showing 
further dialogs, and stop the overall operation. This was not previously done. 
(In some cases, a bunch of dialogs would be shown on top of each other 
simultaneously, creating visual artifacts.)
    
    This change was made to the Close All and Close Other actions, as well as 
for the newly introduced "Close whole documents list at once" button in the 
document list dropdown (PR #4792).
    
    In a previous discussion, it was suggested to make the whole operation 
atomic (i.e. don't close any tabs at all if the user presses Cancel after 
several tabs have already been iterated), but this is not possible given the 
existing APIs. (We don't know if Cancel was pressed until TopComponent.close() 
was called.) Moreover, the behavior implemented in this PR is more standard in 
any case; it matches the behavior in e.g. Photoshop and VSCode.
    
    It was also suggested to implement similar behavior in the save prompt that 
shows up when exiting the IDE, but this is a rather different operation that 
does not actually close any tabs (they remain "open" and persisted for the next 
time the IDE starts). I'm not quite sure how to improve it; it might require 
more discussion. See the "Savable" API and the o.n.core.ExitDialog class.
    
    I would also have liked to focus each TopComponent in turn when prompts to 
save come up, but this is a bit more work due to the various levels of 
abstractions involved. More work on this can be done later. See 
MultiViewFactory.resolveCloseOperation for a relevant starting point.
---
 .../core/multitabs/impl/DocumentSwitcherTable.java | 27 +++++++-
 .../netbeans/core/windows/actions/ActionUtils.java | 71 ++++++++--------------
 2 files changed, 50 insertions(+), 48 deletions(-)

diff --git 
a/platform/core.multitabs/src/org/netbeans/core/multitabs/impl/DocumentSwitcherTable.java
 
b/platform/core.multitabs/src/org/netbeans/core/multitabs/impl/DocumentSwitcherTable.java
index 006a3afc8f..4ff3786b3a 100644
--- 
a/platform/core.multitabs/src/org/netbeans/core/multitabs/impl/DocumentSwitcherTable.java
+++ 
b/platform/core.multitabs/src/org/netbeans/core/multitabs/impl/DocumentSwitcherTable.java
@@ -49,6 +49,7 @@ import org.netbeans.swing.tabcontrol.TabData;
 import org.netbeans.swing.tabcontrol.TabbedContainer;
 import org.netbeans.swing.tabcontrol.event.TabActionEvent;
 import org.openide.awt.CloseButtonFactory;
+import org.openide.windows.TopComponent;
 
 /**
  * Slightly enhanced switcher table which adds close button to selected item
@@ -196,15 +197,35 @@ class DocumentSwitcherTable extends SwitcherTable {
         for ( TabData tab : tabs ) {  
             ProjectProxy projectForTab = projectSupport.getProjectForTab( tab 
);
             if (( project == null && projectForTab == null ) || ( 
projectForTab != null && projectForTab.equals( project ))) {
-                int tabIndex = controller.getTabModel().indexOf( tab );
-                TabActionEvent tae = new TabActionEvent( this, 
TabbedContainer.COMMAND_CLOSE, tabIndex );
-                controller.postActionEvent( tae );
+                Component tabComponent = tab.getComponent();
+                if (tabComponent instanceof TopComponent) {
+                    TopComponent curTC = (TopComponent) tabComponent;
+                    /* As in 
o.n.core.windows.actions.ActionUtils.closeAll(Iterable<TopComponent>).
+                    We have to be a little more general here since, 
theoretically, there could be
+                    tab components that do not extend from TopComponent. */
+                    if(!isClosingEnabled(curTC)) {
+                        continue;
+                    }
+                    curTC.putClientProperty("inCloseAll", Boolean.TRUE);
+                    if (!curTC.close()) {
+                        break;
+                    }
+                } else {
+                    int tabIndex = controller.getTabModel().indexOf( tab );
+                    TabActionEvent tae = new TabActionEvent( this, 
TabbedContainer.COMMAND_CLOSE, tabIndex );
+                    controller.postActionEvent( tae );
+                }
             } else {
                 numOfOtherTabs++;
             }
         }
         return numOfOtherTabs == 0;
     }
+
+    // Copied from o.n.core.windows.Switches.isClosingEnabled (in private 
package).
+    private static boolean isClosingEnabled( TopComponent tc ) {
+        return 
!Boolean.TRUE.equals(tc.getClientProperty(TopComponent.PROP_CLOSING_DISABLED));
+    }
     
     private JButton createCloseButton() {
         JButton res = CloseButtonFactory.createBigCloseButton();
diff --git 
a/platform/core.windows/src/org/netbeans/core/windows/actions/ActionUtils.java 
b/platform/core.windows/src/org/netbeans/core/windows/actions/ActionUtils.java
index e13aed3bb7..043b889edf 100644
--- 
a/platform/core.windows/src/org/netbeans/core/windows/actions/ActionUtils.java
+++ 
b/platform/core.windows/src/org/netbeans/core/windows/actions/ActionUtils.java
@@ -29,7 +29,6 @@ import org.netbeans.core.windows.*;
 import org.netbeans.core.windows.view.ui.slides.SlideController;
 import org.openide.DialogDisplayer;
 import org.openide.NotifyDescriptor;
-import org.openide.awt.Actions;
 import org.openide.awt.Mnemonics;
 import org.openide.cookies.SaveCookie;
 import org.openide.util.*;
@@ -467,30 +466,15 @@ public abstract class ActionUtils {
      * otherwise closes all documents in the system
      */
     public static void closeAllDocuments (boolean isContext) {
-        if (isContext) {
-            TopComponent activeTC = TopComponent.getRegistry().getActivated();
-            List<TopComponent> tcs = getOpened(activeTC);
-
-            closeAll( tcs.toArray(new TopComponent[tcs.size()]) );
-        } else {
-            TopComponent[] tcs = 
WindowManagerImpl.getInstance().getEditorTopComponents();
-            closeAll( tcs );
-        }
-    }
-
-    private static void closeAll( TopComponent[] tcs ) {
-        for( TopComponent tc: tcs ) {
-            if( !Switches.isClosingEnabled(tc) )
-                continue;
-            final TopComponent toBeClosed = tc;
-            SwingUtilities.invokeLater( new Runnable() {
-                @Override
-                public void run() {
-                    toBeClosed.putClientProperty("inCloseAll", Boolean.TRUE);
-                    toBeClosed.close();
-                }
-            });
-        }
+        /* Historically, the closeAll method wrapped calls to 
TopComponent.close() in an
+        invokeLater, so keep doing that. This is probably a good idea e.g. for 
cases where the
+        caller is a button press handler and where TopComponent.close() ends 
up showing a modal
+        dialog (which could perhaps delay the update of the button's visual 
state). */
+        SwingUtilities.invokeLater(() -> {
+            closeAll(isContext
+                ? getOpened(TopComponent.getRegistry().getActivated())
+                : 
Arrays.asList(WindowManagerImpl.getInstance().getEditorTopComponents()));
+        });
     }
 
     /** Closes all documents except given param, according to isContext flag
@@ -500,27 +484,24 @@ public abstract class ActionUtils {
      * given
      */
     public static void closeAllExcept (TopComponent tc, boolean isContext) {
-        if (isContext) {
-            List<TopComponent> tcs = getOpened(tc);
-
-            for(TopComponent curTC: tcs) {
-                if( !Switches.isClosingEnabled(curTC) )
-                    continue;
-                if (curTC != tc) {
-                    curTC.putClientProperty("inCloseAll", Boolean.TRUE);
-                    curTC.close();
-                }
-            }
-        } else {
-            TopComponent[] tcs = 
WindowManagerImpl.getInstance().getEditorTopComponents();
+        // See closeAllDocuments.
+        SwingUtilities.invokeLater(() -> {
+            List<TopComponent> tcs = new ArrayList<>(isContext
+                ? getOpened(tc)
+                : 
Arrays.asList(WindowManagerImpl.getInstance().getEditorTopComponents()));
+            tcs.remove(tc);
+            closeAll(tcs);
+        });
+    }
 
-            for(TopComponent curTC: tcs) {
-                if( !Switches.isClosingEnabled(curTC) )
-                    continue;
-                if (curTC != tc) {
-                    curTC.putClientProperty("inCloseAll", Boolean.TRUE);
-                    curTC.close();
-                }
+    private static void closeAll( Iterable<TopComponent> tcs ) {
+        for (TopComponent curTC : tcs) {
+            if( !Switches.isClosingEnabled(curTC) ) {
+                continue;
+            }
+            curTC.putClientProperty("inCloseAll", Boolean.TRUE);
+            if (!curTC.close()) {
+                break;
             }
         }
     }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@netbeans.apache.org
For additional commands, e-mail: commits-h...@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists

Reply via email to