From ee5dff62c5502a3180efbe867f4c4832189acfac Mon Sep 17 00:00:00 2001 From: David Wolf Date: Thu, 11 Sep 2025 20:53:26 +0200 Subject: [PATCH] Implemented a Close Right feature in menu --- .../core/windows/actions/ActionUtils.java | 16 +++ .../core/windows/actions/Bundle.properties | 3 + .../actions/CloseAllRightOfThisAction.java | 106 ++++++++++++++++++ .../netbeans/core/windows/resources/layer.xml | 5 + .../core/windows/view/ui/TabbedHandler.java | 7 +- .../swing/tabcontrol/TabbedContainer.java | 11 +- 6 files changed, 140 insertions(+), 8 deletions(-) create mode 100644 platform/core.windows/src/org/netbeans/core/windows/actions/CloseAllRightOfThisAction.java 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 827c7cdb3c00..df392ee54622 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 @@ -79,6 +79,10 @@ public static Action[] createDefaultPopupActions(TopComponent tc) { allBut.setEnabled(false); } actions.add(allBut); + //close all right of this + int index = mode.getTopComponentTabPosition(tc); + CloseAllRightOfThisAction allRight = new CloseAllRightOfThisAction(index); + actions.add(allRight); } actions.add(null); // Separator @@ -499,6 +503,18 @@ public static void closeAllExcept (TopComponent tc, boolean isContext) { closeAll(tcs); }); } + + /** + * Closes all documents after given index, according to isContext flag + */ + public static void closeRight(int index) { + // See closeAllDocuments. + SwingUtilities.invokeLater(() -> { + List tcs = new ArrayList<>(getOpened(TopComponent.getRegistry().getActivated())); + closeAll(tcs.subList(index + 1, tcs.size())); + }); + } + private static void closeAll( Iterable tcs ) { for (TopComponent curTC : tcs) { diff --git a/platform/core.windows/src/org/netbeans/core/windows/actions/Bundle.properties b/platform/core.windows/src/org/netbeans/core/windows/actions/Bundle.properties index 2e8aaab641d0..4c6323451281 100644 --- a/platform/core.windows/src/org/netbeans/core/windows/actions/Bundle.properties +++ b/platform/core.windows/src/org/netbeans/core/windows/actions/Bundle.properties @@ -29,6 +29,9 @@ CTL_SwitchToRecentDocumentAction=&Editor CTL_CloseAllDocumentsAction=Close &All Documents +CTL_CloseAllRightOfThisAction=Close Right +CTL_CloseAllRightOfThisAction_MainMenu=Close All Documents Right Of This + # UndockAction CTL_UndockWindowAction=&Float CTL_UndockWindowAction_Dock=Doc&k diff --git a/platform/core.windows/src/org/netbeans/core/windows/actions/CloseAllRightOfThisAction.java b/platform/core.windows/src/org/netbeans/core/windows/actions/CloseAllRightOfThisAction.java new file mode 100644 index 000000000000..9363665c49d6 --- /dev/null +++ b/platform/core.windows/src/org/netbeans/core/windows/actions/CloseAllRightOfThisAction.java @@ -0,0 +1,106 @@ +/* + * 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.core.windows.actions; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import static javax.swing.Action.NAME; +import org.netbeans.core.windows.WindowManagerImpl; +import org.openide.util.NbBundle; +import org.openide.windows.TopComponent; + +/** + * + * @author davidwolf + */ +public class CloseAllRightOfThisAction extends AbstractAction { + + /** + * TopComponent index to mark after which tab should all subsequent tabs be + * closed or -1 for the instance used in the Menu Bar + */ + private int index; + + /** + * Constructor used in Menu Bar menu called "Window" in the "Close All + * Documents Right Of This" option + */ + public CloseAllRightOfThisAction() { + this(-1); + } + + /** + * Constructor used by right clicking on an opened file. + * + * @param index + */ + public CloseAllRightOfThisAction(int index) { + this.index = index; + String key = index == -1 ? "CTL_CloseAllRightOfThisAction_MainMenu" : "CTL_CloseAllRightOfThisAction"; + putValue(NAME, NbBundle.getMessage(CloseAllRightOfThisAction.class, key)); + } + + @Override + public void actionPerformed(java.awt.event.ActionEvent ev) { + // index CANNOT be reassigned because this class is used in Menu Bar where the instance is not regenerated + if (index == -1) { + ActionUtils.closeRight(TopComponent.getRegistry().getActivated().getTabPosition()); + } else { + ActionUtils.closeRight(index); + } + } + + /** + * Overriden to share accelerator with + * org.netbeans.core.windows.actions.ActionUtils.CloseAllRightOfThisAction + */ + @Override + public void putValue(String key, Object newValue) { + if (Action.ACCELERATOR_KEY.equals(key)) { + ActionUtils.putSharedAccelerator("CloseAllRightOfThisAction", newValue); //NOI18N + } else { + super.putValue(key, newValue); + } + } + + /** + * Overriden to share accelerator with + * org.netbeans.core.windows.actions.ActionUtils.CloseAllRightOfThisAction + */ + @Override + public Object getValue(String key) { + if (Action.ACCELERATOR_KEY.equals(key)) { + return ActionUtils.getSharedAccelerator("CloseAllRightOfThisAction"); //NOI18N + } else { + return super.getValue(key); + } + } + + @Override + public boolean isEnabled() { + WindowManagerImpl wmi = WindowManagerImpl.getInstance(); + TopComponent tc = TopComponent.getRegistry().getActivated(); + if (!wmi.isOpenedEditorTopComponent(tc)) { + return false; + } + int i = index == -1 ? tc.getTabPosition() : index; + return i != wmi.getEditorTopComponents().length - 1; + } + +} diff --git a/platform/core.windows/src/org/netbeans/core/windows/resources/layer.xml b/platform/core.windows/src/org/netbeans/core/windows/resources/layer.xml index 96016c7a7de4..61ec7f7f39e9 100644 --- a/platform/core.windows/src/org/netbeans/core/windows/resources/layer.xml +++ b/platform/core.windows/src/org/netbeans/core/windows/resources/layer.xml @@ -64,6 +64,7 @@ + @@ -257,6 +258,10 @@ + + + + diff --git a/platform/core.windows/src/org/netbeans/core/windows/view/ui/TabbedHandler.java b/platform/core.windows/src/org/netbeans/core/windows/view/ui/TabbedHandler.java index 743acbd91aff..e5437913266e 100644 --- a/platform/core.windows/src/org/netbeans/core/windows/view/ui/TabbedHandler.java +++ b/platform/core.windows/src/org/netbeans/core/windows/view/ui/TabbedHandler.java @@ -30,11 +30,9 @@ import java.beans.PropertyChangeListener; import java.util.logging.Level; import java.util.logging.Logger; - import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; - import org.netbeans.core.windows.Constants; import org.netbeans.core.windows.ModeImpl; import org.netbeans.core.windows.Switches; @@ -329,7 +327,10 @@ public void actionPerformed(ActionEvent e) { } else if (TabbedContainer.COMMAND_CLOSE_ALL_BUT_THIS == cmd) { TopComponent tc = tabbed.getTopComponentAt(tae.getTabIndex()); ActionUtils.closeAllExcept(tc, true); - //Pin button handling here + } else if (TabbedContainer.COMMAND_CLOSE_RIGHT.equals(cmd)) { + TopComponent tc = tabbed.getTopComponentAt(tae.getTabIndex()); + ActionUtils.closeRight(tc.getTabPosition()); + //Pin button handling here } else if (TabbedContainer.COMMAND_ENABLE_AUTO_HIDE.equals(cmd)) { if( Switches.isTopComponentSlidingEnabled() && tabbed.getComponent().isShowing() ) { TopComponent tc = tabbed.getTopComponentAt(tae.getTabIndex()); diff --git a/platform/o.n.swing.tabcontrol/src/org/netbeans/swing/tabcontrol/TabbedContainer.java b/platform/o.n.swing.tabcontrol/src/org/netbeans/swing/tabcontrol/TabbedContainer.java index 0d5da666ef83..4c78c80be513 100644 --- a/platform/o.n.swing.tabcontrol/src/org/netbeans/swing/tabcontrol/TabbedContainer.java +++ b/platform/o.n.swing.tabcontrol/src/org/netbeans/swing/tabcontrol/TabbedContainer.java @@ -19,11 +19,6 @@ package org.netbeans.swing.tabcontrol; -import javax.accessibility.Accessible; -import org.netbeans.swing.tabcontrol.event.TabActionEvent; -import org.netbeans.swing.tabcontrol.plaf.DefaultTabbedContainerUI; - -import javax.swing.*; import java.awt.*; import java.awt.event.AWTEventListener; import java.awt.event.ActionListener; @@ -32,8 +27,12 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import javax.accessibility.Accessible; import javax.accessibility.AccessibleRole; +import javax.swing.*; import javax.swing.JComponent.AccessibleJComponent; +import org.netbeans.swing.tabcontrol.event.TabActionEvent; +import org.netbeans.swing.tabcontrol.plaf.DefaultTabbedContainerUI; import org.openide.util.NbBundle; @@ -192,6 +191,8 @@ public class TabbedContainer extends JComponent implements Accessible { public static final String COMMAND_CLOSE_ALL = "closeAll"; //NOI18N public static final String COMMAND_CLOSE_ALL_BUT_THIS = "closeAllButThis"; //NOI18N + + public static final String COMMAND_CLOSE_RIGHT = "closeRight"; //NOI18N public static final String COMMAND_ENABLE_AUTO_HIDE = "enableAutoHide"; //NOI18N