| /* |
| * 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.ide.dnd; |
| |
| import com.intellij.icons.AllIcons; |
| import com.intellij.openapi.ui.MessageType; |
| import com.intellij.openapi.ui.popup.Balloon; |
| import com.intellij.openapi.ui.popup.JBPopupFactory; |
| import com.intellij.openapi.util.registry.Registry; |
| import com.intellij.ui.JBColor; |
| import com.intellij.ui.awt.RelativePoint; |
| |
| import javax.swing.*; |
| import java.awt.*; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| public class Highlighters implements DnDEvent.DropTargetHighlightingType { |
| private static final List<DropTargetHighlighter> ourHightlighters = new ArrayList<DropTargetHighlighter>(); |
| |
| private static final ArrayList<DropTargetHighlighter> ourCurrentHighlighters = new ArrayList<DropTargetHighlighter>(); |
| |
| static { |
| ourHightlighters.add(new RectangleHighlighter()); |
| ourHightlighters.add(new FilledRectangleHighlighter()); |
| ourHightlighters.add(new HorizontalLinesHighlighter()); |
| ourHightlighters.add(new TextHighlighter()); |
| ourHightlighters.add(new ErrorTextHighlighter()); |
| ourHightlighters.add(new VerticalLinesHighlighter()); |
| } |
| |
| static void show(int aType, JLayeredPane aPane, Rectangle aRectangle, DnDEvent aEvent) { |
| List<DropTargetHighlighter> toShow = new ArrayList<DropTargetHighlighter>(); |
| for (DropTargetHighlighter ourHightlighter : ourHightlighters) { |
| DropTargetHighlighter each = (DropTargetHighlighter)ourHightlighter; |
| if ((each.getMask() & aType) != 0) { |
| toShow.add(each); |
| } |
| } |
| |
| for (int i = 0; i < toShow.size(); i++) { |
| DropTargetHighlighter each = toShow.get(i); |
| each.show(aPane, aRectangle, aEvent); |
| } |
| ourCurrentHighlighters.addAll(toShow); |
| } |
| |
| static void hideAllBut(int aType) { |
| for (int i = 0; i < ourCurrentHighlighters.size(); i++) { |
| final DropTargetHighlighter each = ourCurrentHighlighters.get(i); |
| if ((each.getMask() & aType) == 0) { |
| each.vanish(); |
| ourCurrentHighlighters.remove(each); |
| } |
| } |
| } |
| |
| static void hide() { |
| for (int i = 0; i < ourCurrentHighlighters.size(); i++) { |
| (ourCurrentHighlighters.get(i)).vanish(); |
| } |
| ourCurrentHighlighters.clear(); |
| } |
| |
| static void hide(int aType) { |
| for (int i = 0; i < ourCurrentHighlighters.size(); i++) { |
| final DropTargetHighlighter each = ourCurrentHighlighters.get(i); |
| if ((each.getMask() & aType) != 0) { |
| each.vanish(); |
| ourCurrentHighlighters.remove(each); |
| } |
| } |
| } |
| |
| static boolean isVisibleExcept(int type) { |
| int resultType = type; |
| for (int i = 0; i < ourCurrentHighlighters.size(); i++) { |
| final DropTargetHighlighter each = ourCurrentHighlighters.get(i); |
| resultType = resultType | each.getMask(); |
| } |
| |
| return type != resultType; |
| } |
| |
| static boolean isVisible() { |
| return ourCurrentHighlighters.size() > 0; |
| } |
| |
| private static abstract class AbstractComponentHighlighter extends JPanel implements DropTargetHighlighter { |
| |
| protected AbstractComponentHighlighter() { |
| setOpaque(false); |
| setLayout(new BorderLayout()); |
| } |
| |
| public final void show(JLayeredPane aPane, Rectangle aRectangle, DnDEvent aEvent) { |
| if (getParent() != aPane) { |
| vanish(); |
| aPane.add(this, getLayer()); |
| } |
| _show(aPane, aRectangle, aEvent); |
| } |
| |
| protected Integer getLayer() { |
| return JLayeredPane.MODAL_LAYER; |
| } |
| |
| public void vanish() { |
| final Container parent = getParent(); |
| Rectangle bounds = getBounds(); |
| if (parent != null) { |
| parent.remove(this); |
| parent.repaint(bounds.x, bounds.y, bounds.width, bounds.height); |
| } |
| } |
| |
| protected abstract void _show(JLayeredPane aPane, Rectangle aRectangle, DnDEvent aEvent); |
| } |
| |
| public abstract static class BaseTextHighlighter implements DropTargetHighlighter { |
| |
| private Balloon myCurrentBalloon; |
| private MessageType myMessageType; |
| |
| public BaseTextHighlighter(MessageType type) { |
| myMessageType = type; |
| } |
| |
| public void show(JLayeredPane aPane, Rectangle aRectangle, DnDEvent aEvent) { |
| if (!Registry.is("ide.dnd.textHints")) return; |
| |
| final String result = aEvent.getExpectedDropResult(); |
| if (result != null && result.length() > 0) { |
| RelativePoint point = null; |
| for (DropTargetHighlighter each : ourHightlighters) { |
| if (each instanceof AbstractComponentHighlighter) { |
| Rectangle rec = ((AbstractComponentHighlighter)each).getBounds(); |
| point = new RelativePoint(aPane, new Point(rec.x + rec.width, rec.y + rec.height / 2)); |
| break; |
| } |
| } |
| |
| if (point == null) { |
| point = new RelativePoint(aPane, new Point(aRectangle.x + aRectangle.width, aRectangle.y + aRectangle.height / 2)); |
| } |
| |
| myCurrentBalloon = JBPopupFactory.getInstance().createHtmlTextBalloonBuilder(result, myMessageType, null).createBalloon(); |
| myCurrentBalloon.show(point, Balloon.Position.atRight); |
| } |
| } |
| |
| public void vanish() { |
| if (myCurrentBalloon != null) { |
| myCurrentBalloon.hide(); |
| myCurrentBalloon = null; |
| } |
| } |
| |
| protected Integer getLayer() { |
| return JLayeredPane.POPUP_LAYER; |
| } |
| |
| } |
| |
| public static class TextHighlighter extends BaseTextHighlighter { |
| |
| public TextHighlighter() { |
| super(MessageType.INFO); |
| } |
| |
| public int getMask() { |
| return TEXT; |
| } |
| } |
| |
| private static class ErrorTextHighlighter extends BaseTextHighlighter { |
| public ErrorTextHighlighter() { |
| super(MessageType.ERROR); |
| } |
| |
| public int getMask() { |
| return ERROR_TEXT; |
| } |
| } |
| |
| private static class FilledRectangleHighlighter extends AbstractComponentHighlighter { |
| public FilledRectangleHighlighter() { |
| super(); |
| setOpaque(true); |
| setBorder(BorderFactory.createLineBorder(JBColor.RED)); |
| setBackground(JBColor.RED); |
| } |
| |
| protected void _show(JLayeredPane aPane, Rectangle aRectangle, DnDEvent aEvent) { |
| setBounds(aRectangle); |
| } |
| |
| public int getMask() { |
| return FILLED_RECTANGLE; |
| } |
| } |
| |
| private static class RectangleHighlighter extends AbstractComponentHighlighter { |
| public RectangleHighlighter() { |
| super(); |
| setOpaque(false); |
| setBorder(BorderFactory.createLineBorder(JBColor.RED)); |
| } |
| |
| protected void _show(JLayeredPane aPane, Rectangle aRectangle, DnDEvent aEvent) { |
| setBounds(aRectangle); |
| } |
| |
| public int getMask() { |
| return RECTANGLE; |
| } |
| } |
| |
| private static class HorizontalLinesHighlighter extends AbstractComponentHighlighter { |
| |
| protected void _show(JLayeredPane aPane, Rectangle aRectangle, DnDEvent aEvent) { |
| final Rectangle rectangle = new Rectangle(aRectangle.x - AllIcons.Ide.Dnd.Left.getIconWidth(), aRectangle.y - AllIcons.Ide.Dnd.Left |
| .getIconHeight(), aRectangle.width + AllIcons.Ide.Dnd.Left.getIconWidth() + AllIcons.Ide.Dnd.Right.getIconWidth(), aRectangle.height + AllIcons.Ide.Dnd.Left |
| .getIconHeight()); |
| setBounds(rectangle); |
| } |
| |
| protected void paintComponent(Graphics g) { |
| AllIcons.Ide.Dnd.Left.paintIcon(this, g, 0, (getHeight() / 2)); |
| AllIcons.Ide.Dnd.Right.paintIcon(this, g, getWidth() - AllIcons.Ide.Dnd.Right.getIconWidth(), (getHeight() / 2)); |
| } |
| |
| public int getMask() { |
| return H_ARROWS; |
| } |
| } |
| |
| private static class VerticalLinesHighlighter extends AbstractComponentHighlighter { |
| private static final Icon TOP = AllIcons.Ide.Dnd.Top; |
| private static final Icon BOTTOM = AllIcons.Ide.Dnd.Bottom; |
| |
| protected void _show(JLayeredPane aPane, Rectangle aRectangle, DnDEvent aEvent) { |
| final Rectangle rectangle = new Rectangle(aRectangle.x, aRectangle.y - TOP.getIconHeight(), aRectangle.width, aRectangle.height + TOP.getIconHeight() + BOTTOM |
| .getIconHeight()); |
| setBounds(rectangle); |
| } |
| |
| protected void paintComponent(Graphics g) { |
| TOP.paintIcon(this, g, (getWidth() - TOP.getIconWidth()) / 2, 0); |
| BOTTOM.paintIcon(this, g, (getWidth() - BOTTOM.getIconWidth()) / 2, getHeight() - BOTTOM.getIconHeight()); |
| } |
| |
| public int getMask() { |
| return V_ARROWS; |
| } |
| } |
| } |