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
;
27 import java
.util
.HashMap
;
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
) {
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
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
);
92 private void putToolTip(Component relativeTo
, Point pnt
, @Nullable String text
) {
94 if (myToolTip
.getParent() == this) {
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) {
112 else if (!text
.equals(oldText
)) {
118 public void removeFeedback() {
119 boolean needRepaint
= false;
120 if (myFeedbackPainterPanel
.getParent() == this) {
121 remove(myFeedbackPainterPanel
);
124 if (myToolTip
.getParent() == this) {
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() {
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();
154 myFeedbackPainter
.paintFeedback(g2d
, new Rectangle(0, 0, getWidth(), getHeight()));
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
) {
172 protected void selectionChanged(RadComponent component
, boolean selected
) {
173 ListenerNavigateButton btn
= myNavigateButtons
.get(component
);
175 DefaultActionGroup group
= component
.getBinding() != null ? ListenerNavigateButton
.prepareActionGroup(component
) : null;
176 if (group
!= null && group
.getChildrenCount() > 0) {
178 btn
= new ListenerNavigateButton(component
);
179 myNavigateButtons
.put(component
, btn
);
182 btn
.setVisible(true);
186 btn
.setVisible(false);
192 btn
.setVisible(false);