From f0c75f3abdbadb82d3abbafecc7355264c0dc119 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Fri, 2 Nov 2012 15:43:33 +0400 Subject: [PATCH] IDEA-19061 Integrate the Rearranger-plugin into core-IDE Show atom condition's close icon only when mouse is over the component --- .../codeStyle/arrangement/InsetsPanel.java | 55 ++++++++++++++++ .../newui/ArrangementListRowDecorator.java | 4 +- .../newui/ArrangementMatchingRulesList.java | 2 +- ...ArrangementAndMatchConditionComponent.java | 61 ++++++++++++++--- ...rrangementAtomMatchConditionComponent.java | 65 +++++++++++++------ ...gementEditIconMatchConditionComponent.java | 9 ++- ...gementGroupingMatchConditionComponent.java | 5 ++ .../ArrangementMatchConditionComponent.java | 3 + 8 files changed, 173 insertions(+), 31 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/InsetsPanel.java diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/InsetsPanel.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/InsetsPanel.java new file mode 100644 index 000000000000..97b11c61efd9 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/InsetsPanel.java @@ -0,0 +1,55 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed 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 com.intellij.application.options.codeStyle.arrangement; + +import com.intellij.util.ui.GridBag; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.awt.*; + +/** + * Panel which occupies horizontal and vertical space even if it's content is invisible. + * + * @author Denis Zhdanov + * @since 11/2/12 3:08 PM + */ +public class InsetsPanel extends JPanel { + + @NotNull private final JComponent myContent; + + public InsetsPanel(@NotNull JComponent content) { + super(new GridBagLayout()); + setOpaque(false); + myContent = content; + add(myContent, new GridBag().fillCell().weightx(1).weighty(1)); + } + + @Override + public Dimension getPreferredSize() { + return myContent.getPreferredSize(); + } + + @Override + public Dimension getMinimumSize() { + return myContent.getMinimumSize(); + } + + @Override + public Dimension getMaximumSize() { + return myContent.getMaximumSize(); + } +} diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/newui/ArrangementListRowDecorator.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/newui/ArrangementListRowDecorator.java index db3c91fae181..ebb5e7138020 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/newui/ArrangementListRowDecorator.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/newui/ArrangementListRowDecorator.java @@ -124,8 +124,10 @@ public class ArrangementListRowDecorator extends JPanel implements ArrangementMa myDelegate.setSelected(selected); } - public void onMouseEntered() { + @Override + public Rectangle onMouseEntered(@NotNull MouseEvent e) { setBackground(UIUtil.getDecoratedRowColor()); + return myDelegate.onMouseEntered(e); } @Nullable diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/newui/ArrangementMatchingRulesList.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/newui/ArrangementMatchingRulesList.java index 604c3b55a16c..9eb0f84d625d 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/newui/ArrangementMatchingRulesList.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/newui/ArrangementMatchingRulesList.java @@ -155,7 +155,7 @@ public class ArrangementMatchingRulesList extends JBList { myRowUnderMouse = locationToIndex(e.getPoint()); ArrangementListRowDecorator decorator = myComponents.get(myRowUnderMouse); if (decorator != null) { - decorator.onMouseEntered(); + decorator.onMouseEntered(e); repaintRows(myRowUnderMouse, myRowUnderMouse, false); } } diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementAndMatchConditionComponent.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementAndMatchConditionComponent.java index 3e4db73f6bd3..0d3153a89d8d 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementAndMatchConditionComponent.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementAndMatchConditionComponent.java @@ -49,6 +49,7 @@ public class ArrangementAndMatchConditionComponent extends JPanel implements Arr @NotNull private final ArrangementCompositeMatchCondition mySetting; @Nullable private Rectangle myScreenBounds; + @Nullable private ArrangementMatchConditionComponent myComponentUnderMouse; public ArrangementAndMatchConditionComponent(@NotNull StdArrangementMatchRule rule, @NotNull ArrangementCompositeMatchCondition setting, @@ -165,11 +166,43 @@ public class ArrangementAndMatchConditionComponent extends JPanel implements Arr Point location = event.getLocationOnScreen(); for (ArrangementMatchConditionComponent component : myComponents) { Rectangle bounds = component.getScreenBounds(); - if (bounds != null && bounds.contains(location)) { - return component.onMouseMove(event); + if (bounds == null || !bounds.contains(location)) { + continue; + } + if (myComponentUnderMouse == null) { + myComponentUnderMouse = component; + Rectangle rectangleOnEnter = myComponentUnderMouse.onMouseEntered(event); + Rectangle rectangleOnMove = myComponentUnderMouse.onMouseMove(event); + if (rectangleOnEnter != null && rectangleOnMove != null) { + return myScreenBounds; // Repaint row + } + else if (rectangleOnEnter != null) { + return rectangleOnEnter; + } + else { + return rectangleOnMove; + } + } + else { + if (myComponentUnderMouse != component) { + myComponentUnderMouse.onMouseExited(); + myComponentUnderMouse = component; + component.onMouseEntered(event); + return myScreenBounds; // Repaint row. + } + else { + return component.onMouseMove(event); + } } } - return null; + if (myComponentUnderMouse == null) { + return null; + } + else { + Rectangle result = myComponentUnderMouse.onMouseExited(); + myComponentUnderMouse = null; + return result; + } } @Override @@ -184,14 +217,26 @@ public class ArrangementAndMatchConditionComponent extends JPanel implements Arr } } + @Override + public Rectangle onMouseEntered(@NotNull MouseEvent event) { + Point location = event.getLocationOnScreen(); + for (ArrangementMatchConditionComponent component : myComponents) { + Rectangle bounds = component.getScreenBounds(); + if (bounds != null && bounds.contains(location)) { + myComponentUnderMouse = component; + return component.onMouseEntered(event); + } + } + return null; + } + @Nullable @Override public Rectangle onMouseExited() { - for (ArrangementMatchConditionComponent component : myComponents) { - Rectangle bounds = component.onMouseExited(); - if (bounds != null) { - return bounds; - } + if (myComponentUnderMouse != null) { + Rectangle result = myComponentUnderMouse.onMouseExited(); + myComponentUnderMouse = null; + return result; } return null; } diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementAtomMatchConditionComponent.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementAtomMatchConditionComponent.java index a00e1daa40bc..c54bc55b3958 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementAtomMatchConditionComponent.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementAtomMatchConditionComponent.java @@ -83,6 +83,7 @@ public class ArrangementAtomMatchConditionComponent implements ArrangementMatchC @NotNull private final ArrangementAtomMatchCondition myCondition; @Nullable private final ActionButton myCloseButton; + @Nullable private final Rectangle myCloseButtonBounds; @Nullable private final Consumer myCloseCallback; @NotNull private Color myBackgroundColor; @@ -109,13 +110,20 @@ public class ArrangementAtomMatchConditionComponent implements ArrangementMatchC final ArrangementRemoveConditionAction action = new ArrangementRemoveConditionAction(); Icon buttonIcon = action.getTemplatePresentation().getIcon(); Dimension buttonSize = new Dimension(buttonIcon.getIconWidth(), buttonIcon.getIconHeight()); - myCloseButton = new ActionButton(action, action.getTemplatePresentation().clone(), ArrangementConstants.RULE_TREE_PLACE, buttonSize) { - @Override - protected Icon getIcon() { - return myCloseButtonHovered ? action.getTemplatePresentation().getHoveredIcon() : action.getTemplatePresentation().getIcon(); - } - }; - + if (closeCallback == null) { + myCloseButton = null; + myCloseButtonBounds = null; + } + else { + myCloseButton = new ActionButton(action, action.getTemplatePresentation().clone(), ArrangementConstants.RULE_TREE_PLACE, buttonSize) { + @Override + protected Icon getIcon() { + return myCloseButtonHovered ? action.getTemplatePresentation().getHoveredIcon() : action.getTemplatePresentation().getIcon(); + } + }; + myCloseButtonBounds = new Rectangle(0, 0, buttonIcon.getIconWidth(), buttonIcon.getIconHeight()); + } + GridBagConstraints constraints = new GridBag().anchor(GridBagConstraints.WEST).weightx(1).insets(0, 0, 0, 0); JPanel insetsPanel = new JPanel(new GridBagLayout()); @@ -127,7 +135,7 @@ public class ArrangementAtomMatchConditionComponent implements ArrangementMatchC JPanel roundBorderPanel = new JPanel(new GridBagLayout()) { @Override public void paint(Graphics g) { - Rectangle buttonBounds = getCloseButtonScreenLocation(); + Rectangle buttonBounds = getCloseButtonScreenBounds(); if (buttonBounds != null) { Point mouseScreenLocation = MouseInfo.getPointerInfo().getLocation(); myCloseButtonHovered = buttonBounds.contains(mouseScreenLocation); @@ -140,7 +148,9 @@ public class ArrangementAtomMatchConditionComponent implements ArrangementMatchC } }; roundBorderPanel.add(insetsPanel, new GridBag().fillCellHorizontally().anchor(GridBagConstraints.WEST)); - roundBorderPanel.add(myCloseButton, new GridBag().anchor(GridBagConstraints.EAST)); + if (myCloseButton != null) { + roundBorderPanel.add(new InsetsPanel(myCloseButton), new GridBag().anchor(GridBagConstraints.EAST)); + } myBorder = IdeBorderFactory.createRoundedBorder(arcSize); roundBorderPanel.setBorder(myBorder); roundBorderPanel.setOpaque(false); @@ -148,6 +158,9 @@ public class ArrangementAtomMatchConditionComponent implements ArrangementMatchC myRenderer.add(roundBorderPanel, constraints); myRenderer.setOpaque(false); setSelected(false); + if (myCloseButton != null) { + myCloseButton.setVisible(false); + } } @NotNull @@ -208,38 +221,52 @@ public class ArrangementAtomMatchConditionComponent implements ArrangementMatchC @Nullable @Override public Rectangle onMouseMove(@NotNull MouseEvent event) { - Rectangle buttonBounds = getCloseButtonScreenLocation(); + Rectangle buttonBounds = getCloseButtonScreenBounds(); if (buttonBounds == null) { return null; } + if (myCloseButton != null && !myCloseButton.isVisible()) { + myCloseButton.setVisible(true); + return buttonBounds; + } boolean mouseOverButton = buttonBounds.contains(event.getLocationOnScreen()); return (mouseOverButton ^ myCloseButtonHovered) ? buttonBounds : null; } @Override public void onMouseClick(@NotNull MouseEvent event) { - Rectangle buttonBounds = getCloseButtonScreenLocation(); + Rectangle buttonBounds = getCloseButtonScreenBounds(); if (buttonBounds != null && myCloseCallback != null && buttonBounds.contains(event.getLocationOnScreen())) { myCloseCallback.consume(getMatchCondition()); } } - @Nullable @Override - public Rectangle onMouseExited() { - Rectangle result = myCloseButtonHovered ? getCloseButtonScreenLocation() : null; - myCloseButtonHovered = false; - return result; + public Rectangle onMouseEntered(@NotNull MouseEvent e) { + if (myCloseButton != null) { + myCloseButton.setVisible(true); + return getCloseButtonScreenBounds(); + } + return null; } @Nullable - private Rectangle getCloseButtonScreenLocation() { + @Override + public Rectangle onMouseExited() { + if (myCloseButton == null) { + return null; + } + myCloseButton.setVisible(false); + return getCloseButtonScreenBounds(); + } + + @Nullable + private Rectangle getCloseButtonScreenBounds() { if (myCloseButton == null || myScreenBounds == null) { return null; } - Rectangle buttonBounds = myCloseButton.getBounds(); - buttonBounds = SwingUtilities.convertRectangle(myCloseButton.getParent(), buttonBounds, myRenderer); + Rectangle buttonBounds = SwingUtilities.convertRectangle(myCloseButton.getParent(), myCloseButtonBounds, myRenderer); buttonBounds.x += myScreenBounds.x; buttonBounds.y += myScreenBounds.y; return buttonBounds; diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementEditIconMatchConditionComponent.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementEditIconMatchConditionComponent.java index c24e7b0d5e6b..ae4cc3387a28 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementEditIconMatchConditionComponent.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementEditIconMatchConditionComponent.java @@ -180,8 +180,8 @@ public class ArrangementEditIconMatchConditionComponent extends JPanel implement } @Override - public String toString() { - return "'edit' decorator for " + myDelegate.toString(); + public Rectangle onMouseEntered(@NotNull MouseEvent e) { + return null; } @Nullable @@ -189,4 +189,9 @@ public class ArrangementEditIconMatchConditionComponent extends JPanel implement public Rectangle onMouseExited() { return null; } + + @Override + public String toString() { + return "'edit' decorator for " + myDelegate.toString(); + } } diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementGroupingMatchConditionComponent.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementGroupingMatchConditionComponent.java index ac589b5c3867..b51c4653e062 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementGroupingMatchConditionComponent.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementGroupingMatchConditionComponent.java @@ -121,6 +121,11 @@ public class ArrangementGroupingMatchConditionComponent extends JPanel implement } } + @Override + public Rectangle onMouseEntered(@NotNull MouseEvent e) { + return null; + } + @Nullable @Override public Rectangle onMouseExited() { diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementMatchConditionComponent.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementMatchConditionComponent.java index fea8693f1c5c..c0c800b782dc 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementMatchConditionComponent.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementMatchConditionComponent.java @@ -83,4 +83,7 @@ public interface ArrangementMatchConditionComponent { @Nullable Rectangle onMouseExited(); + + @Nullable + Rectangle onMouseEntered(@NotNull MouseEvent e); }