diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/ActionPlaces.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/ActionPlaces.java index 36d9b8174d69..ad3c97ab53fe 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/ActionPlaces.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/ActionPlaces.java @@ -29,6 +29,7 @@ public abstract class ActionPlaces { public static final String EDITOR_TOOLBAR = "EditorToolbar"; public static final String EDITOR_TAB_POPUP = "EditorTabPopup"; public static final String EDITOR_TAB = "EditorTab"; + public static final String TABS_MORE_TOOLBAR = "TabsMoreToolbar"; public static final String EDITOR_GUTTER = "ICON_NAVIGATION"; public static final String EDITOR_GUTTER_POPUP = "ICON_NAVIGATION_SECONDARY_BUTTON"; public static final String RIGHT_EDITOR_GUTTER_POPUP = "RightEditorGutterPopup"; @@ -150,7 +151,7 @@ public abstract class ActionPlaces { private static final Set ourCommonPlaces = ContainerUtil.newHashSet( UNKNOWN, KEYBOARD_SHORTCUT, MOUSE_SHORTCUT, FORCE_TOUCH, - TOOLBAR, MAIN_MENU, MAIN_TOOLBAR, EDITOR_TOOLBAR, EDITOR_TAB, COMMANDER_TOOLBAR, CONTEXT_TOOLBAR, TOOLWINDOW_TITLE, + TOOLBAR, MAIN_MENU, MAIN_TOOLBAR, EDITOR_TOOLBAR, TABS_MORE_TOOLBAR, EDITOR_TAB, COMMANDER_TOOLBAR, CONTEXT_TOOLBAR, TOOLWINDOW_TITLE, PROJECT_VIEW_TOOLBAR, STATUS_BAR_PLACE, ACTION_SEARCH, TESTTREE_VIEW_TOOLBAR, TYPE_HIERARCHY_VIEW_TOOLBAR, METHOD_HIERARCHY_VIEW_TOOLBAR, CALL_HIERARCHY_VIEW_TOOLBAR, RUNNER_TOOLBAR, DEBUGGER_TOOLBAR, USAGE_VIEW_TOOLBAR, STRUCTURE_VIEW_TOOLBAR, NAVIGATION_BAR_TOOLBAR, TODO_VIEW_TOOLBAR, COMPILER_MESSAGES_TOOLBAR, diff --git a/platform/platform-api/src/com/intellij/ui/tabs/JBTabsEx.java b/platform/platform-api/src/com/intellij/ui/tabs/JBTabsEx.java index ffac0651663f..475a667f4087 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/JBTabsEx.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/JBTabsEx.java @@ -6,7 +6,6 @@ import com.intellij.openapi.util.ActionCallback; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.awt.event.MouseEvent; import java.util.Comparator; /** @@ -19,10 +18,6 @@ public interface JBTabsEx extends JBTabs { void updateTabActions(boolean validateNow); - boolean canShowMorePopup(); - - void showMorePopup(@Nullable MouseEvent e); - TabInfo addTabSilently(TabInfo info, int index); @NotNull diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java index 3cc1648a7b21..a1912db349f8 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java @@ -11,6 +11,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.rd.RdIdeaKt; import com.intellij.openapi.ui.*; +import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.util.*; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.IdeFocusManager; @@ -52,7 +53,7 @@ import static com.intellij.openapi.wm.IdeFocusManager.getGlobalInstance; public class JBTabsImpl extends JComponent implements JBTabsEx, PropertyChangeListener, TimerListener, DataProvider, PopupMenuListener, Disposable, JBTabsPresentation, Queryable, - UISettingsListener, QuickActionProvider, Accessible { + UISettingsListener, QuickActionProvider, MorePopupAware, Accessible { public static final Key SIDE_TABS_SIZE_LIMIT_KEY = Key.create("SIDE_TABS_SIZE_LIMIT_KEY"); static final int MIN_TAB_WIDTH = JBUIScale.scale(75); @@ -69,6 +70,7 @@ public class JBTabsImpl extends JComponent private TabInfo mySelectedInfo; public final Map myInfo2Label = new HashMap<>(); public final Map myInfo2Toolbar = new HashMap<>(); + public final ActionToolbar myMoreToolbar; public Dimension myHeaderFitSize; private Insets myInnerInsets = JBUI.emptyInsets(); @@ -243,17 +245,13 @@ public class JBTabsImpl extends JComponent disposePopupListener(); } }; - - addMouseListener(new MouseAdapter() { - @Override - public void mousePressed(final MouseEvent e) { - if (mySingleRowLayout.myLastSingRowLayout != null && - mySingleRowLayout.myLastSingRowLayout.moreRect != null && - mySingleRowLayout.myLastSingRowLayout.moreRect.contains(e.getPoint())) { - showMorePopup(e); - } - } - }); + AnAction tabListAction = myActionManager.getAction("TabList"); + myMoreToolbar = myActionManager + .createActionToolbar(ActionPlaces.TABS_MORE_TOOLBAR, new DefaultActionGroup(tabListAction), true); + myMoreToolbar.getComponent().setBorder(JBUI.Borders.empty()); + myMoreToolbar.getComponent().setOpaque(false); + myMoreToolbar.setLayoutPolicy(ActionToolbar.NOWRAP_LAYOUT_POLICY); + add(myMoreToolbar.getComponent()); addMouseWheelListener(event -> { int units = event.getUnitsToScroll(); if (units == 0) return; @@ -332,7 +330,7 @@ public class JBTabsImpl extends JComponent myGlassPane = gp; UIUtil.addAwtListener(__ -> { - if (mySingleRowLayout.myMorePopup != null) return; + if (!JBPopupFactory.getInstance().getChildPopups(JBTabsImpl.this).isEmpty()) return; processFocusChange(); }, AWTEvent.FOCUS_EVENT_MASK, child); @@ -712,53 +710,35 @@ public class JBTabsImpl extends JComponent } } - @Override - public boolean canShowMorePopup() { - final SingleRowPassInfo lastLayout = mySingleRowLayout.myLastSingRowLayout; - return lastLayout != null && lastLayout.moreRect != null; + private Rectangle getMoreRect() { + SingleRowPassInfo lastLayout = mySingleRowLayout.myLastSingRowLayout; + return lastLayout != null ? lastLayout.moreRect : null; } @Override - public void showMorePopup(@Nullable final MouseEvent e) { - final SingleRowPassInfo lastLayout = mySingleRowLayout.myLastSingRowLayout; - if (lastLayout == null) { - return; - } - mySingleRowLayout.myMorePopup = new JBPopupMenu(); + public boolean canShowMorePopup() { + return getMoreRect() != null; + } + + @Override + public void showMorePopup() { + Rectangle rect = getMoreRect(); + if (rect == null) return; + + JBPopupMenu menu = new JBPopupMenu(); for (final TabInfo each : getVisibleInfos()) { if (!mySingleRowLayout.isTabHidden(each)) continue; - final JBMenuItem item = new JBMenuItem(each.getText(), each.getIcon()); - item.setForeground(each.getDefaultForeground()); - item.setBackground(each.getTabColor()); - mySingleRowLayout.myMorePopup.add(item); - item.addActionListener(__ -> select(each, true)); + menu.add(createMenuItem(each)); } + menu.show(this, rect.x, rect.y + rect.height); + } - mySingleRowLayout.myMorePopup.addPopupMenuListener(new PopupMenuListener() { - @Override - public void popupMenuWillBecomeVisible(final PopupMenuEvent e) { - } - - @Override - public void popupMenuWillBecomeInvisible(final PopupMenuEvent e) { - mySingleRowLayout.myMorePopup = null; - } - - @Override - public void popupMenuCanceled(final PopupMenuEvent e) { - mySingleRowLayout.myMorePopup = null; - } - }); - - if (e != null) { - mySingleRowLayout.myMorePopup.show(this, e.getX(), e.getY()); - } - else { - final Rectangle rect = lastLayout.moreRect; - if (rect != null) { - mySingleRowLayout.myMorePopup.show(this, rect.x, rect.y + rect.height); - } - } + private JBMenuItem createMenuItem(@NotNull TabInfo tabInfo) { + final JBMenuItem item = new JBMenuItem(tabInfo.getText(), tabInfo.getIcon()); + item.setForeground(tabInfo.getDefaultForeground()); + item.setBackground(tabInfo.getTabColor()); + item.addActionListener(__ -> select(tabInfo, true)); + return item; } @@ -1512,6 +1492,20 @@ public class JBTabsImpl extends JComponent if (isSingleRow()) { mySingleRowLayout.scrollSelectionInView(); myLastLayoutPass = mySingleRowLayout.layoutSingleRow(visible); + Rectangle moreRect = getMoreRect(); + if (moreRect != null) { + Dimension preferredSize = myMoreToolbar.getComponent().getPreferredSize(); + Rectangle bounds = new Rectangle(moreRect); + int xDiff = (bounds.width - preferredSize.width) / 2; + int yDiff = (bounds.height - preferredSize.height) / 2; + bounds.x += xDiff + 1; + bounds.width -= 2 * xDiff; + bounds.y += yDiff; + bounds.height -= 2* yDiff; + myMoreToolbar.getComponent().setBounds(bounds); + } else { + myMoreToolbar.getComponent().setBounds(new Rectangle()); + } myTableLayout.myLastTableLayout = null; OnePixelDivider divider = mySplitter.getDivider(); if (divider.getParent() == this) { @@ -1716,12 +1710,6 @@ public class JBTabsImpl extends JComponent return JBSwingUtilities.runGlobalCGTransform(this, super.getComponentGraphics(graphics)); } - @Override - protected void paintChildren(final Graphics g) { - super.paintChildren(g); - mySingleRowLayout.myMoreIcon.paintIcon(this, g); - } - protected void drawBorder(Graphics g) { if (!isHideTabs()) { myBorder.paintBorder(this, g, 0, 0, getWidth(), getHeight()); @@ -2530,6 +2518,9 @@ public class JBTabsImpl extends JComponent if (QuickActionProvider.KEY.getName().equals(dataId)) { return this; } + if (MorePopupAware.KEY.is(dataId)) { + return this; + } return NAVIGATION_ACTIONS_KEY.is(dataId) ? this : null; } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/MorePopupAware.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/MorePopupAware.java new file mode 100644 index 000000000000..c3e88060b736 --- /dev/null +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/MorePopupAware.java @@ -0,0 +1,11 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.ui.tabs.impl; + +import com.intellij.openapi.actionSystem.DataKey; + +public interface MorePopupAware { + DataKey KEY = DataKey.create("MorePopupAware"); + + boolean canShowMorePopup(); + void showMorePopup(); +} diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/MoreTabsIcon.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/MoreTabsIcon.java deleted file mode 100644 index a8852dd8654b..000000000000 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/MoreTabsIcon.java +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -package com.intellij.ui.tabs.impl.singleRow; - -import com.intellij.icons.AllIcons; -import com.intellij.ide.ui.UISettings; -import com.intellij.ui.ColorUtil; -import com.intellij.ui.JBColor; -import com.intellij.util.ui.UIUtil; -import org.jetbrains.annotations.Nullable; - -import javax.swing.*; -import java.awt.*; - -/** - * @author pegov - */ -public abstract class MoreTabsIcon { - private final Icon icon = AllIcons.General.MoreTabs; - private int myCounter; - - public void paintIcon(final Component c, Graphics graphics) { - if (myCounter <= 0) - return; - final Rectangle moreRect = getIconRec(); - - if (moreRect == null) return; - - int iconY = getIconY(moreRect); - int iconX = getIconX(moreRect); - graphics.setFont(UIUtil.getLabelFont().deriveFont((float)Math.min(8, UIUtil.getButtonFont().getSize()))); - int width = graphics.getFontMetrics().stringWidth(String.valueOf(myCounter)); - iconX -= width / 2 + 1; - - icon.paintIcon(c, graphics, iconX, iconY); - Graphics g = graphics.create(); - try { - UISettings.setupAntialiasing(g); - UIUtil.drawStringWithHighlighting(g, String.valueOf(myCounter), - iconX + getIconWidth() + 2, - iconY + getIconHeight() - 5, - JBColor.BLACK, - ColorUtil.withPreAlpha(JBColor.WHITE, .9)); - } finally { - g.dispose(); - } - } - - public int getIconWidth() { - return icon.getIconWidth(); - } - - public int getIconHeight() { - return icon.getIconHeight(); - } - - protected int getIconX(final Rectangle iconRec) { - return iconRec.x + iconRec.width / 2 - (getIconWidth()) / 2; - } - - protected int getIconY(final Rectangle iconRec) { - return iconRec.y + iconRec.height / 2 - getIconHeight() / 2; - } - - @Nullable - protected abstract Rectangle getIconRec(); - - public void updateCounter(int counter) { - myCounter = counter; - } -} diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java index 7a557d1af757..9f18e09d0fb4 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java @@ -6,7 +6,6 @@ import com.intellij.ui.tabs.impl.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.swing.*; import java.awt.*; import java.lang.ref.WeakReference; import java.util.List; @@ -21,15 +20,6 @@ public abstract class SingleRowLayout extends TabLayout { private final SingleRowLayoutStrategy myBottom; private final SingleRowLayoutStrategy myRight; - public final MoreTabsIcon myMoreIcon = new MoreTabsIcon() { - @Override - @Nullable - protected Rectangle getIconRec() { - return myLastSingRowLayout != null ? myLastSingRowLayout.moreRect : null; - } - }; - public JPopupMenu myMorePopup; - @Override public boolean isSideComponentOnTabs() { return getStrategy().isSideComponentOnTabs(); @@ -135,8 +125,6 @@ public abstract class SingleRowLayout extends TabLayout { getStrategy().layoutComp(data); } - updateMoreIconVisibility(data); - data.tabRectangle = new Rectangle(); if (data.toLayout.size() > 0) { @@ -173,11 +161,6 @@ public abstract class SingleRowLayout extends TabLayout { data.toFitLength = getStrategy().getToFitLength(data); } - protected void updateMoreIconVisibility(SingleRowPassInfo data) { - int counter = (int)data.myVisibleInfos.stream().filter(this::isTabHidden).count(); - myMoreIcon.updateCounter(counter); - } - protected void layoutMoreButton(SingleRowPassInfo data) { if (data.toDrop.size() > 0) { data.moreRect = getStrategy().getMoreRect(data); diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayoutStrategy.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayoutStrategy.java index 658ed0abc4c9..033181594916 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayoutStrategy.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayoutStrategy.java @@ -1,7 +1,7 @@ // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.ui.tabs.impl.singleRow; -import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.ActionToolbar; import com.intellij.ui.tabs.impl.JBTabsImpl; import com.intellij.ui.tabs.impl.ShapeTransform; import com.intellij.ui.tabs.impl.TabLabel; @@ -89,7 +89,7 @@ public abstract class SingleRowLayoutStrategy { @Override public int getMoreRectAxisSize() { - return AllIcons.General.MoreTabs.getIconWidth() + 15; + return ActionToolbar.DEFAULT_MINIMUM_BUTTON_SIZE.width + 2; } @Override @@ -173,8 +173,7 @@ public abstract class SingleRowLayoutStrategy { else { x = data.position; } - return new Rectangle(x, data.insets.top + JBTabsImpl.getSelectionTabVShift(), - data.moreRectAxisSize - 1, myTabs.myHeaderFitSize.height); + return new Rectangle(x, 1, data.moreRectAxisSize - 1, myTabs.myHeaderFitSize.height); } @@ -268,7 +267,7 @@ public abstract class SingleRowLayoutStrategy { @Override int getMoreRectAxisSize() { - return AllIcons.General.MoreTabs.getIconHeight() + 4; + return ActionToolbar.DEFAULT_MINIMUM_BUTTON_SIZE.width + 2; } @Override diff --git a/platform/platform-impl/src/com/intellij/ide/actions/TabListAction.java b/platform/platform-impl/src/com/intellij/ide/actions/TabListAction.java index 4377bedaeae0..28499507b436 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/TabListAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/TabListAction.java @@ -1,9 +1,11 @@ // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.ide.actions; +import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.ActionPlaces; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.ui.tabs.JBTabsEx; +import com.intellij.ui.tabs.impl.MorePopupAware; import org.jetbrains.annotations.NotNull; /** @@ -14,22 +16,21 @@ import org.jetbrains.annotations.NotNull; public class TabListAction extends AnAction { @Override public void actionPerformed(@NotNull AnActionEvent e) { - JBTabsEx tabs = e.getData(JBTabsEx.NAVIGATION_ACTIONS_KEY); - if (tabs != null) { - tabs.showMorePopup(null); + MorePopupAware morePopupAware = e.getData(MorePopupAware.KEY); + if (morePopupAware != null) { + morePopupAware.showMorePopup(); } } @Override public void update(@NotNull AnActionEvent e) { - e.getPresentation().setEnabled(isTabListAvailable(e)); + e.getPresentation().setIcon(AllIcons.Actions.FindAndShowNextMatches); + boolean available = isTabListAvailable(e) || e.getPlace() == ActionPlaces.TABS_MORE_TOOLBAR; + e.getPresentation().setEnabledAndVisible(available); } private static boolean isTabListAvailable(@NotNull AnActionEvent e) { - JBTabsEx tabs = e.getData(JBTabsEx.NAVIGATION_ACTIONS_KEY); - if (tabs == null || !tabs.isEditorTabs()) { - return false; - } - return tabs.canShowMorePopup(); + MorePopupAware morePopupAware = e.getData(MorePopupAware.KEY); + return morePopupAware != null && morePopupAware.canShowMorePopup(); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java index 1d947bb75afc..4174b6e8f4de 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java @@ -14,11 +14,13 @@ import com.intellij.ui.DoubleClickListener; import com.intellij.ui.PopupHandler; import com.intellij.ui.UIBundle; import com.intellij.ui.components.panels.NonOpaquePanel; +import com.intellij.ui.tabs.impl.MorePopupAware; import com.intellij.ui.tabs.impl.SingleHeightTabs; import com.intellij.util.ui.*; import com.intellij.util.ui.accessibility.AccessibleContextUtil; import net.miginfocom.swing.MigLayout; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.plaf.PanelUI; @@ -32,7 +34,7 @@ import java.util.function.Supplier; /** * @author pegov */ -public abstract class ToolWindowHeader extends JPanel implements UISettingsListener { +public abstract class ToolWindowHeader extends JPanel implements UISettingsListener, DataProvider { @NotNull private final Supplier myGearProducer; @NotNull @@ -63,9 +65,11 @@ public abstract class ToolWindowHeader extends JPanel implements UISettingsListe ToolWindowContentUi.initMouseListeners(myWestPanel, toolWindow.getContentUI(), true); - myToolbar = ActionManager.getInstance().createActionToolbar( + ActionManager actionManager = ActionManager.getInstance(); + AnAction tabListAction = actionManager.getAction("TabList"); + myToolbar = actionManager.createActionToolbar( ActionPlaces.TOOLWINDOW_TITLE, - new DefaultActionGroup(myActionGroup, new ShowOptionsAction(), new HideAction()), + new DefaultActionGroup(tabListAction, myActionGroup, new ShowOptionsAction(), new HideAction()), true); myToolbar.setTargetComponent(this); myToolbar.setLayoutPolicy(ActionToolbar.NOWRAP_LAYOUT_POLICY); @@ -131,6 +135,15 @@ public abstract class ToolWindowHeader extends JPanel implements UISettingsListe }); } + @Nullable + @Override + public Object getData(@NotNull String dataId) { + if (MorePopupAware.KEY.is(dataId) && myToolWindow instanceof ToolWindowImpl) { + return ((ToolWindowImpl)myToolWindow).getContentUI().getData(dataId); + } + return null; + } + private void initWestToolBar(JPanel westPanel) { myToolbarWest = ActionManager.getInstance().createActionToolbar(ActionPlaces.TOOLWINDOW_TITLE, new DefaultActionGroup(myActionGroupWest), diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/TabContentLayout.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/TabContentLayout.java index 861e347cf565..781a91dc0aa1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/TabContentLayout.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/TabContentLayout.java @@ -4,6 +4,7 @@ package com.intellij.openapi.wm.impl.content; import com.intellij.ide.dnd.DnDSupport; import com.intellij.ide.dnd.DnDTarget; import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.ListPopup; import com.intellij.openapi.util.text.StringUtil; @@ -16,7 +17,7 @@ import com.intellij.ui.content.TabbedContent; import com.intellij.ui.scale.JBUIScale; import com.intellij.ui.tabs.JBTabPainter; import com.intellij.ui.tabs.JBTabsPosition; -import com.intellij.ui.tabs.impl.singleRow.MoreTabsIcon; +import com.intellij.ui.tabs.impl.MorePopupAware; import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.BaseButtonBehavior; @@ -28,7 +29,7 @@ import java.awt.event.MouseEvent; import java.util.List; import java.util.*; -final class TabContentLayout extends ContentLayout { +final class TabContentLayout extends ContentLayout implements MorePopupAware { static final int MORE_ICON_BORDER = 6; public static final int TAB_LAYOUT_START = 4; LayoutData myLastLayout; @@ -36,13 +37,6 @@ final class TabContentLayout extends ContentLayout { ArrayList myTabs = new ArrayList<>(); final Map myContent2Tabs = new HashMap<>(); - private final MoreTabsIcon myMoreIcon = new MoreTabsIcon() { - @Override - @Nullable - protected Rectangle getIconRec() { - return myLastLayout.moreRect; - } - }; List myDoubleClickActions = new ArrayList<>(); TabContentLayout(ToolWindowContentUi ui) { @@ -52,12 +46,9 @@ final class TabContentLayout extends ContentLayout { @Override protected void execute(final MouseEvent e) { if (!myUi.isCurrent(TabContentLayout.this)) return; - - if (myLastLayout != null) { - final Rectangle moreRect = myLastLayout.moreRect; - if (moreRect != null && moreRect.contains(e.getPoint())) { - showPopup(e, ContainerUtil.filter(myTabs, myLastLayout.toDrop::contains)); - } + Rectangle moreRect = getMoreRect(); + if (moreRect != null) { + showMorePopup(); } } }; @@ -91,10 +82,25 @@ final class TabContentLayout extends ContentLayout { myDoubleClickActions = ContainerUtil.newArrayList(actions); } - private static void showPopup(MouseEvent e, List tabs) { + private Rectangle getMoreRect() { + if (myLastLayout == null) return null; + return myLastLayout.moreRect; + } + + @Override + public boolean canShowMorePopup() { + return getMoreRect() != null; + } + + @Override + public void showMorePopup() { + Rectangle rect = getMoreRect(); + if (rect == null) return; + List tabs = ContainerUtil.filter(myTabs, myLastLayout.toDrop::contains); final List contentsToShow = ContainerUtil.map(tabs, ContentTabLabel::getContent); final SelectContentStep step = new SelectContentStep(contentsToShow); - JBPopupFactory.getInstance().createListPopup(step).show(new RelativePoint(e)); + RelativePoint point = new RelativePoint(myUi, new Point(rect.x, rect.y + rect.height)); + JBPopupFactory.getInstance().createListPopup(step).show(point); } @Override @@ -140,7 +146,6 @@ final class TabContentLayout extends ContentLayout { } - data.moreRectWidth = calcMoreIconWidth(); data.toFitWidth = bounds.getSize().width - data.eachX; final ContentTabLabel selectedTab = myContent2Tabs.get(selected); @@ -170,7 +175,7 @@ final class TabContentLayout extends ContentLayout { } else { if (!reachedBounds) { - final int width = bounds.width - data.eachX - data.moreRectWidth; + final int width = bounds.width - data.eachX; each.setBounds(data.eachX, data.eachY, width, bounds.height - data.eachY); data.eachX += width; } @@ -185,23 +190,23 @@ final class TabContentLayout extends ContentLayout { each.setBounds(0, 0, 0, 0); } } - + boolean toolbarUpdateNeeded; if (data.toDrop.size() > 0) { - data.moreRect = new Rectangle(data.eachX + MORE_ICON_BORDER, 0, myMoreIcon.getIconWidth(), bounds.height); - myMoreIcon.updateCounter(data.toDrop.size()); + toolbarUpdateNeeded = myLastLayout != null && myLastLayout.moreRect == null; + data.moreRect = new Rectangle(data.eachX + MORE_ICON_BORDER, 0, /*getMoreToolbarWidth()*/16, bounds.height); } else { + toolbarUpdateNeeded = myLastLayout != null && myLastLayout.moreRect != null; data.moreRect = null; } - final Rectangle moreRect = data.moreRect == null ? null : new Rectangle(data.eachX, 0, myMoreIcon.getIconWidth()+MORE_ICON_BORDER, bounds.height); + final Rectangle moreRect = data.moreRect == null ? null : new Rectangle(data.eachX, 0, /*getMoreToolbarWidth()*/16+MORE_ICON_BORDER, bounds.height); myUi.isResizableArea = p -> moreRect == null || !moreRect.contains(p); myLastLayout = data; - } - - private int calcMoreIconWidth() { - return myMoreIcon.getIconWidth() + MORE_ICON_BORDER * TAB_ARC; + if (toolbarUpdateNeeded) { + ActionToolbarImpl.updateAllToolbarsImmediately(); + } } @Override @@ -221,7 +226,7 @@ final class TabContentLayout extends ContentLayout { selected = contentManager.getContents()[0]; } - result += selected != null ? myContent2Tabs.get(selected).getMinimumSize().width + (myTabs.size() > 1 ? calcMoreIconWidth() : 0) : 0; + result += selected != null ? myContent2Tabs.get(selected).getMinimumSize().width : 0; return result; } @@ -229,9 +234,6 @@ final class TabContentLayout extends ContentLayout { static void dropTab(final LayoutData data, final ContentTabLabel toDropLabel) { data.requiredWidth -= (toDropLabel.getPreferredSize().width + 1); data.toDrop.add(toDropLabel); - if (data.toDrop.size() == 1) { - data.toFitWidth -= data.moreRectWidth; - } } boolean isToDrawTabs() { @@ -251,8 +253,6 @@ final class TabContentLayout extends ContentLayout { Dimension layoutSize; boolean fullLayout = true; - int moreRectWidth; - ArrayList toLayout = new ArrayList<>(); Collection toDrop = new HashSet<>(); @@ -295,10 +295,6 @@ final class TabContentLayout extends ContentLayout { @Override public void paintChildren(Graphics g) { if (!isToDrawTabs()) return; - - if (myLastLayout != null && myLastLayout.moreRect != null) { - myMoreIcon.paintIcon(myUi, g); - } } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/ToolWindowContentUi.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/ToolWindowContentUi.java index 2a2ab1fd9c07..c9ab255adb3d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/ToolWindowContentUi.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/ToolWindowContentUi.java @@ -24,6 +24,7 @@ import com.intellij.ui.PopupHandler; import com.intellij.ui.content.*; import com.intellij.ui.content.tabs.PinToolwindowTabAction; import com.intellij.ui.content.tabs.TabbedContentAction; +import com.intellij.ui.tabs.impl.MorePopupAware; import com.intellij.util.Alarm; import com.intellij.util.ContentUtilEx; import com.intellij.util.containers.JBIterable; @@ -621,6 +622,9 @@ public final class ToolWindowContentUi extends JPanel implements ContentUI, Data } else if (CloseAction.CloseTarget.KEY.is(dataId)) { return computeCloseTarget(); + } else if (MorePopupAware.KEY.is(dataId)) { + ContentLayout layout = getCurrentLayout(); + return (layout instanceof TabContentLayout) ? layout : null; } return null; }