mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-19061 Integrate the Rearranger-plugin into core-IDE
Showing 'close' icon for the condition nodes
This commit is contained in:
+13
@@ -26,6 +26,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -194,6 +195,18 @@ public class ArrangementAndNodeComponent extends JPanel implements ArrangementNo
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle handleMouseMove(@NotNull MouseEvent event) {
|
||||
Point location = event.getLocationOnScreen();
|
||||
for (ArrangementNodeComponent component : myComponents) {
|
||||
Rectangle bounds = component.getScreenBounds();
|
||||
if (bounds != null && bounds.contains(location)) {
|
||||
return component.handleMouseMove(event);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("(%s)", StringUtil.join(myComponents, " and "));
|
||||
|
||||
+77
-5
@@ -15,9 +15,11 @@
|
||||
*/
|
||||
package com.intellij.application.options.codeStyle.arrangement;
|
||||
|
||||
import com.intellij.openapi.actionSystem.impl.ActionButton;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsAtomNode;
|
||||
import com.intellij.ui.IdeBorderFactory;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.ui.GridBag;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -25,9 +27,12 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
/**
|
||||
* // TODO den add doc
|
||||
* {@link ArrangementNodeComponent} for {@link ArrangementSettingsAtomNode} representation.
|
||||
* <p/>
|
||||
* Not thread-safe.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 8/8/12 10:06 AM
|
||||
@@ -68,7 +73,8 @@ public class ArrangementAtomNodeComponent implements ArrangementNodeComponent {
|
||||
}
|
||||
};
|
||||
|
||||
@NotNull private final ArrangementSettingsAtomNode mySettingsNode;
|
||||
@NotNull private final ArrangementSettingsAtomNode mySettingsNode;
|
||||
@Nullable private final ActionButton myCloseButton;
|
||||
|
||||
@Nullable private Dimension mySize;
|
||||
@Nullable private Rectangle myScreenBounds;
|
||||
@@ -76,18 +82,60 @@ public class ArrangementAtomNodeComponent implements ArrangementNodeComponent {
|
||||
private boolean myEnabled = true;
|
||||
private boolean mySelected;
|
||||
private boolean myInverted;
|
||||
private boolean myCloseButtonHovered;
|
||||
|
||||
public ArrangementAtomNodeComponent(@NotNull ArrangementNodeDisplayManager manager, @NotNull ArrangementSettingsAtomNode node) {
|
||||
public ArrangementAtomNodeComponent(@NotNull ArrangementNodeDisplayManager manager,
|
||||
@NotNull ArrangementSettingsAtomNode node,
|
||||
@Nullable Consumer<ArrangementSettingsAtomNode> closeCallback)
|
||||
{
|
||||
mySettingsNode = node;
|
||||
myLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
myLabel.setText(manager.getDisplayValue(node));
|
||||
mySize = new Dimension(manager.getMaxWidth(node.getType()), myLabel.getPreferredSize().height);
|
||||
|
||||
int width = manager.getMaxWidth(node.getType());
|
||||
int height = myLabel.getPreferredSize().height;
|
||||
final ArrangementRemoveConditionAction action;
|
||||
if (closeCallback == null) {
|
||||
myCloseButton = null;
|
||||
action = null;
|
||||
}
|
||||
else {
|
||||
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();
|
||||
}
|
||||
};
|
||||
Dimension preferredButtonSize = myCloseButton.getPreferredSize();
|
||||
width += preferredButtonSize.width;
|
||||
height = Math.max(height, preferredButtonSize.height);
|
||||
}
|
||||
|
||||
mySize = new Dimension(width, height);
|
||||
|
||||
GridBagConstraints constraints = new GridBag().anchor(GridBagConstraints.CENTER).insets(0, 0, 0, 0);
|
||||
|
||||
JPanel labelPanel = new JPanel(new GridBagLayout());
|
||||
JPanel labelPanel = new JPanel(new GridBagLayout()) {
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
Rectangle buttonBounds = getCloseButtonScreenLocation();
|
||||
if (buttonBounds != null && action != null) {
|
||||
Point mouseScreenLocation = MouseInfo.getPointerInfo().getLocation();
|
||||
myCloseButtonHovered = buttonBounds.contains(mouseScreenLocation);
|
||||
}
|
||||
super.paint(g);
|
||||
}
|
||||
};
|
||||
myLabel.setBackground(Color.red);
|
||||
labelPanel.add(myLabel, constraints);
|
||||
if (myCloseButton != null) {
|
||||
labelPanel.add(myCloseButton, new GridBag().anchor(GridBagConstraints.EAST).insets(0, 0, 0, 0));
|
||||
}
|
||||
|
||||
labelPanel.setBorder(IdeBorderFactory.createEmptyBorder(PADDING));
|
||||
labelPanel.setOpaque(false);
|
||||
|
||||
@@ -168,6 +216,30 @@ public class ArrangementAtomNodeComponent implements ArrangementNodeComponent {
|
||||
myInverted = inverted;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Rectangle handleMouseMove(@NotNull MouseEvent event) {
|
||||
Rectangle buttonBounds = getCloseButtonScreenLocation();
|
||||
if (buttonBounds == null) {
|
||||
return null;
|
||||
}
|
||||
boolean mouseOverButton = buttonBounds.contains(event.getLocationOnScreen());
|
||||
return (mouseOverButton ^ myCloseButtonHovered) ? buttonBounds : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Rectangle getCloseButtonScreenLocation() {
|
||||
if (myCloseButton == null || myScreenBounds == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Rectangle buttonBounds = myCloseButton.getBounds();
|
||||
buttonBounds = SwingUtilities.convertRectangle(myCloseButton.getParent(), buttonBounds, myRenderer);
|
||||
buttonBounds.x += myScreenBounds.x;
|
||||
buttonBounds.y += myScreenBounds.y;
|
||||
return buttonBounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return myLabel.getText();
|
||||
|
||||
+1
@@ -25,6 +25,7 @@ public class ArrangementConstants {
|
||||
|
||||
@NonNls public static final String ACTION_GROUP_RULE_EDITOR_CONTEXT_MENU = "Arrangement.RuleEditor.Context.Menu";
|
||||
@NonNls public static final String RULE_EDITOR_PLACE = "Arrangement.RuleEditor.Place";
|
||||
@NonNls public static final String RULE_TREE_PLACE = "Arrangement.RuleTree.Place";
|
||||
|
||||
private ArrangementConstants() {
|
||||
}
|
||||
|
||||
+1
-1
@@ -80,7 +80,7 @@ public class ArrangementMatcherRuleEditor extends JPanel {
|
||||
|
||||
JPanel valuesPanel = new MultiRowFlowPanel(FlowLayout.LEFT, 8, 5);
|
||||
for (Object value : manager.sort(values)) {
|
||||
ArrangementAtomNodeComponent component = new ArrangementAtomNodeComponent(manager, new ArrangementSettingsAtomNode(key, value));
|
||||
ArrangementAtomNodeComponent component = new ArrangementAtomNodeComponent(manager, new ArrangementSettingsAtomNode(key, value), null);
|
||||
myComponents.put(value, component);
|
||||
valuesPanel.add(component.getUiComponent());
|
||||
}
|
||||
|
||||
+14
@@ -22,6 +22,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
/**
|
||||
* // TODO den add doc
|
||||
@@ -54,4 +55,17 @@ public interface ArrangementNodeComponent {
|
||||
* @param selected flag that indicates if current component should be drawn as 'selected'
|
||||
*/
|
||||
void setSelected(boolean selected);
|
||||
|
||||
/**
|
||||
* Instructs current component about mose move event.
|
||||
* <p/>
|
||||
* Primary intention is to allow to react on event like 'on mouse hover' etc. We can't do that by subscribing to the
|
||||
* mouse events at the {@link #getUiComponent() corresponding UI control} because it's used only as a renderer and is not put
|
||||
* to the containers hierarchy, hence, doesn't receive mouse events.
|
||||
*
|
||||
* @param event target mouse move event
|
||||
* @return bounds to be repainted (in screen coordinates) if any; <code>null</code> otherwise
|
||||
*/
|
||||
@Nullable
|
||||
Rectangle handleMouseMove(@NotNull MouseEvent event);
|
||||
}
|
||||
|
||||
+9
-3
@@ -17,6 +17,7 @@ package com.intellij.application.options.codeStyle.arrangement;
|
||||
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.*;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@@ -26,9 +27,13 @@ import org.jetbrains.annotations.NotNull;
|
||||
public class ArrangementNodeComponentFactory {
|
||||
|
||||
@NotNull private final ArrangementNodeDisplayManager myDisplayManager;
|
||||
private Consumer<ArrangementSettingsAtomNode> myRemoveConditionCallback;
|
||||
|
||||
public ArrangementNodeComponentFactory(@NotNull ArrangementNodeDisplayManager manager) {
|
||||
public ArrangementNodeComponentFactory(@NotNull ArrangementNodeDisplayManager manager,
|
||||
@NotNull Consumer<ArrangementSettingsAtomNode> removeConditionCallback)
|
||||
{
|
||||
myDisplayManager = manager;
|
||||
myRemoveConditionCallback = removeConditionCallback;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -37,13 +42,14 @@ public class ArrangementNodeComponentFactory {
|
||||
node.invite(new ArrangementSettingsNodeVisitor() {
|
||||
@Override
|
||||
public void visit(@NotNull ArrangementSettingsAtomNode node) {
|
||||
ref.set(new ArrangementAtomNodeComponent(myDisplayManager, node));
|
||||
ref.set(new ArrangementAtomNodeComponent(myDisplayManager, node, myRemoveConditionCallback));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(@NotNull ArrangementSettingsCompositeNode node) {
|
||||
switch (node.getOperator()) {
|
||||
case AND: ref.set(new ArrangementAndNodeComponent(node, ArrangementNodeComponentFactory.this, myDisplayManager)); break;
|
||||
case AND:
|
||||
ref.set(new ArrangementAndNodeComponent(node, ArrangementNodeComponentFactory.this, myDisplayManager)); break;
|
||||
case OR: // TODO den implement
|
||||
}
|
||||
}
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 8/23/12 11:41 AM
|
||||
*/
|
||||
public class ArrangementRemoveConditionAction extends AnAction {
|
||||
|
||||
private static final Icon ICON = AllIcons.Actions.CloseNew;
|
||||
private static final Icon HOVER_ICON = AllIcons.Actions.CloseNewHovered;
|
||||
|
||||
public ArrangementRemoveConditionAction() {
|
||||
getTemplatePresentation().setIcon(ICON);
|
||||
getTemplatePresentation().setHoveredIcon(HOVER_ICON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
// TODO den implement
|
||||
System.out.println("ArrangementRemoveConditionAction.actionPerformed()");
|
||||
}
|
||||
}
|
||||
+37
-5
@@ -24,6 +24,7 @@ import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
|
||||
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementSettingsGrouper;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.ui.treeStructure.Tree;
|
||||
import com.intellij.util.Consumer;
|
||||
import gnu.trove.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -67,7 +68,12 @@ public class ArrangementRuleTree {
|
||||
private boolean mySkipSelectionChange;
|
||||
|
||||
public ArrangementRuleTree(@NotNull ArrangementSettingsGrouper grouper, @NotNull ArrangementNodeDisplayManager displayManager) {
|
||||
myFactory = new ArrangementNodeComponentFactory(displayManager);
|
||||
myFactory = new ArrangementNodeComponentFactory(displayManager, new Consumer<ArrangementSettingsAtomNode>() {
|
||||
@Override
|
||||
public void consume(@NotNull ArrangementSettingsAtomNode node) {
|
||||
removeConditionFromActiveModel(node);
|
||||
}
|
||||
});
|
||||
myRoot = new ArrangementTreeNode(null);
|
||||
myTreeModel = new DefaultTreeModel(myRoot);
|
||||
myTree = new Tree(myTreeModel) {
|
||||
@@ -117,6 +123,12 @@ public class ArrangementRuleTree {
|
||||
}
|
||||
}
|
||||
});
|
||||
myTree.addMouseMotionListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
onMouseMoved(e);
|
||||
}
|
||||
});
|
||||
myTree.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
@@ -159,7 +171,7 @@ public class ArrangementRuleTree {
|
||||
myTree.setShowsRootHandles(false);
|
||||
myTree.setCellRenderer(new MyCellRenderer());
|
||||
}
|
||||
|
||||
|
||||
private void selectPreviousRule() {
|
||||
ArrangementTreeNode currentSelectionBottom = getCurrentSelectionBottom();
|
||||
|
||||
@@ -338,6 +350,22 @@ public class ArrangementRuleTree {
|
||||
return result;
|
||||
}
|
||||
|
||||
private void removeConditionFromActiveModel(@NotNull ArrangementSettingsAtomNode condition) {
|
||||
// TODO den implement
|
||||
System.out.println("Remove condition " + condition);
|
||||
}
|
||||
|
||||
private void onMouseMoved(@NotNull MouseEvent e) {
|
||||
ArrangementNodeComponent component = getNodeComponentAt(e.getLocationOnScreen());
|
||||
if (component == null) {
|
||||
return;
|
||||
}
|
||||
Rectangle changedScreenRectangle = component.handleMouseMove(e);
|
||||
if (changedScreenRectangle != null) {
|
||||
repaintScreenBounds(changedScreenRectangle);
|
||||
}
|
||||
}
|
||||
|
||||
private void onMouseClicked(@NotNull MouseEvent e) {
|
||||
ArrangementNodeComponent component = getNodeComponentAt(e.getLocationOnScreen());
|
||||
if (component != null) {
|
||||
@@ -381,12 +409,16 @@ public class ArrangementRuleTree {
|
||||
private void repaintComponent(@NotNull ArrangementNodeComponent component) {
|
||||
Rectangle bounds = component.getScreenBounds();
|
||||
if (bounds != null) {
|
||||
Point location = bounds.getLocation();
|
||||
SwingUtilities.convertPointFromScreen(location, myTree);
|
||||
myTree.repaint(location.x, location.y, bounds.width, bounds.height);
|
||||
repaintScreenBounds(bounds);
|
||||
}
|
||||
}
|
||||
|
||||
private void repaintScreenBounds(@NotNull Rectangle bounds) {
|
||||
Point location = bounds.getLocation();
|
||||
SwingUtilities.convertPointFromScreen(location, myTree);
|
||||
myTree.repaint(location.x, location.y, bounds.width, bounds.height);
|
||||
}
|
||||
|
||||
private void notifySelectionListeners(@Nullable ArrangementRuleEditingModel model) {
|
||||
for (ArrangementRuleSelectionListener listener : myListeners) {
|
||||
if (model == null) {
|
||||
|
||||
Reference in New Issue
Block a user