ComponentWithBrowseButton - optional remove listener on hide
[fedora-idea.git] / plugins / ui-designer / src / com / intellij / uiDesigner / designSurface / ActiveDecorationLayer.java
blob6df0a4da21546dc2a4b1d47ca7f0fa2bfeca752f
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.uiDesigner.designSurface;
18 import com.intellij.openapi.actionSystem.DefaultActionGroup;
19 import com.intellij.openapi.diagnostic.Logger;
20 import com.intellij.uiDesigner.SelectionWatcher;
21 import com.intellij.uiDesigner.radComponents.RadComponent;
22 import org.jetbrains.annotations.NotNull;
23 import org.jetbrains.annotations.Nullable;
25 import javax.swing.*;
26 import java.awt.*;
27 import java.util.HashMap;
28 import java.util.Map;
30 /**
31 * Decoration layer is over COMPONENT_LAYER (layer where all components are located).
32 * It contains all necessary decorators. Decorators are:
33 * - special mini-buttons to perform editing of grids (add/remove of columns)
35 * @author Anton Katilin
36 * @author Vladimir Kondratyev
38 final class ActiveDecorationLayer extends JComponent implements FeedbackLayer {
39 private static final Logger LOG = Logger.getInstance("#com.intellij.uiDesigner.designSurface.ActiveDecorationLayer");
41 private final GuiEditor myEditor;
42 private final JToolTip myToolTip;
44 private final Map<RadComponent, ListenerNavigateButton> myNavigateButtons = new HashMap<RadComponent, ListenerNavigateButton>();
46 private final FeedbackPainterPanel myFeedbackPainterPanel = new FeedbackPainterPanel();
47 private final RectangleFeedbackPainter myRectangleFeedbackPainter = new RectangleFeedbackPainter();
49 public ActiveDecorationLayer(@NotNull final GuiEditor editor) {
50 myEditor = editor;
51 myToolTip = new JToolTip();
54 public void installSelectionWatcher() {
55 new MyNavigateButtonSelectionWatcher(myEditor);
58 public void paint(final Graphics g){
59 layoutListenerNavigateButtons();
61 // Paint active decorators
62 paintChildren(g);
65 private void layoutListenerNavigateButtons() {
66 for(Map.Entry<RadComponent, ListenerNavigateButton> e: myNavigateButtons.entrySet()) {
67 RadComponent c = e.getKey();
68 ListenerNavigateButton btn = e.getValue();
69 if (btn.isVisible()) {
70 Rectangle rc = SwingUtilities.convertRectangle(c.getDelegee().getParent(), c.getBounds(), this);
71 btn.setLocation(rc.x, rc.y+rc.height);
76 public void putFeedback(Component relativeTo, final Rectangle rc, final String tooltipText) {
77 putFeedback(relativeTo, rc, myRectangleFeedbackPainter, tooltipText);
80 public void putFeedback(Component relativeTo, Rectangle rc, final FeedbackPainter feedbackPainter, final String tooltipText) {
81 rc = SwingUtilities.convertRectangle(relativeTo, rc, this);
82 myFeedbackPainterPanel.setBounds(rc);
83 myFeedbackPainterPanel.setPainter(feedbackPainter != null ? feedbackPainter : myRectangleFeedbackPainter);
84 Point pntMouse = myEditor.getGlassLayer().getLastMousePosition();
85 putToolTip(this, new Point(pntMouse.x+20, pntMouse.y+30), tooltipText);
86 if (myFeedbackPainterPanel.getParent() != this) {
87 add(myFeedbackPainterPanel);
88 repaint();
92 private void putToolTip(Component relativeTo, Point pnt, @Nullable String text) {
93 if (text == null) {
94 if (myToolTip.getParent() == this) {
95 remove(myToolTip);
96 repaint();
99 else {
100 String oldText = myToolTip.getTipText();
101 myToolTip.setTipText(text);
103 pnt = SwingUtilities.convertPoint(relativeTo, pnt, this);
104 Dimension prefSize = myToolTip.getPreferredSize();
105 pnt.x = Math.min(pnt.x, getBounds().width - prefSize.width);
106 pnt.y = Math.min(pnt.y, getBounds().height - prefSize.height);
107 myToolTip.setBounds(pnt.x, pnt.y, prefSize.width, prefSize.height);
108 if (myToolTip.getParent() != this) {
109 add(myToolTip);
110 repaint();
112 else if (!text.equals(oldText)) {
113 myToolTip.repaint();
118 public void removeFeedback() {
119 boolean needRepaint = false;
120 if (myFeedbackPainterPanel.getParent() == this) {
121 remove(myFeedbackPainterPanel);
122 needRepaint = true;
124 if (myToolTip.getParent() == this) {
125 remove(myToolTip);
126 needRepaint = true;
128 if (needRepaint) repaint();
131 private static class RectangleFeedbackPainter implements FeedbackPainter {
133 public void paintFeedback(Graphics2D g2d, Rectangle rc) {
134 g2d.setColor(Color.BLUE);
135 g2d.setStroke(new BasicStroke(2.5f));
136 // give space for stroke to be painted
137 g2d.drawRect(rc.x+1, rc.y+1, rc.x+rc.width-2, rc.y+rc.height-2);
141 private static class FeedbackPainterPanel extends JPanel {
142 private FeedbackPainter myFeedbackPainter;
144 public FeedbackPainterPanel() {
145 setOpaque(false);
148 protected void paintComponent(Graphics g) {
149 super.paintComponent(g);
150 Graphics2D g2d = (Graphics2D) g;
151 final Stroke savedStroke = g2d.getStroke();
152 final Color savedColor = g2d.getColor();
153 try {
154 myFeedbackPainter.paintFeedback(g2d, new Rectangle(0, 0, getWidth(), getHeight()));
156 finally {
157 g2d.setStroke(savedStroke);
158 g2d.setColor(savedColor);
162 public void setPainter(final FeedbackPainter feedbackPainter) {
163 myFeedbackPainter = feedbackPainter;
167 private class MyNavigateButtonSelectionWatcher extends SelectionWatcher {
168 public MyNavigateButtonSelectionWatcher(final GuiEditor editor) {
169 super(editor);
172 protected void selectionChanged(RadComponent component, boolean selected) {
173 ListenerNavigateButton btn = myNavigateButtons.get(component);
174 if (selected) {
175 DefaultActionGroup group = component.getBinding() != null ? ListenerNavigateButton.prepareActionGroup(component) : null;
176 if (group != null && group.getChildrenCount() > 0) {
177 if (btn == null) {
178 btn = new ListenerNavigateButton(component);
179 myNavigateButtons.put(component, btn);
181 add(btn);
182 btn.setVisible(true);
184 else {
185 if (btn != null) {
186 btn.setVisible(false);
190 else {
191 if (btn != null) {
192 btn.setVisible(false);