blob: 643ca4265478aa89229d15d565454673ee063fc7 [file] [log] [blame]
/*
* 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.uiDesigner.designSurface;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.uiDesigner.SelectionWatcher;
import com.intellij.uiDesigner.radComponents.RadComponent;
import com.intellij.util.ui.PlatformColors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.HashMap;
import java.util.Map;
/**
* Decoration layer is over COMPONENT_LAYER (layer where all components are located).
* It contains all necessary decorators. Decorators are:
* - special mini-buttons to perform editing of grids (add/remove of columns)
*
* @author Anton Katilin
* @author Vladimir Kondratyev
*/
final class ActiveDecorationLayer extends JComponent implements FeedbackLayer {
private static final Logger LOG = Logger.getInstance("#com.intellij.uiDesigner.designSurface.ActiveDecorationLayer");
private final GuiEditor myEditor;
private final JToolTip myToolTip;
private final Map<RadComponent, ListenerNavigateButton> myNavigateButtons = new HashMap<RadComponent, ListenerNavigateButton>();
private final FeedbackPainterPanel myFeedbackPainterPanel = new FeedbackPainterPanel();
private final RectangleFeedbackPainter myRectangleFeedbackPainter = new RectangleFeedbackPainter();
public ActiveDecorationLayer(@NotNull final GuiEditor editor) {
myEditor = editor;
myToolTip = new JToolTip();
}
public void installSelectionWatcher() {
new MyNavigateButtonSelectionWatcher(myEditor);
}
public void paint(final Graphics g){
layoutListenerNavigateButtons();
// Paint active decorators
paintChildren(g);
}
private void layoutListenerNavigateButtons() {
for(Map.Entry<RadComponent, ListenerNavigateButton> e: myNavigateButtons.entrySet()) {
RadComponent c = e.getKey();
ListenerNavigateButton btn = e.getValue();
if (btn.isVisible()) {
Rectangle rc = SwingUtilities.convertRectangle(c.getDelegee().getParent(), c.getBounds(), this);
btn.setLocation(rc.x, rc.y+rc.height);
}
}
}
public void putFeedback(Component relativeTo, final Rectangle rc, final String tooltipText) {
putFeedback(relativeTo, rc, myRectangleFeedbackPainter, tooltipText);
}
public void putFeedback(Component relativeTo, Rectangle rc, final FeedbackPainter feedbackPainter, final String tooltipText) {
rc = SwingUtilities.convertRectangle(relativeTo, rc, this);
myFeedbackPainterPanel.setBounds(rc);
myFeedbackPainterPanel.setPainter(feedbackPainter != null ? feedbackPainter : myRectangleFeedbackPainter);
Point pntMouse = myEditor.getGlassLayer().getLastMousePosition();
putToolTip(this, new Point(pntMouse.x+20, pntMouse.y+30), tooltipText);
if (myFeedbackPainterPanel.getParent() != this) {
add(myFeedbackPainterPanel);
repaint();
}
}
private void putToolTip(Component relativeTo, Point pnt, @Nullable String text) {
if (text == null) {
if (myToolTip.getParent() == this) {
remove(myToolTip);
repaint();
}
}
else {
String oldText = myToolTip.getTipText();
myToolTip.setTipText(text);
pnt = SwingUtilities.convertPoint(relativeTo, pnt, this);
Dimension prefSize = myToolTip.getPreferredSize();
pnt.x = Math.min(pnt.x, getBounds().width - prefSize.width);
pnt.y = Math.min(pnt.y, getBounds().height - prefSize.height);
myToolTip.setBounds(pnt.x, pnt.y, prefSize.width, prefSize.height);
if (myToolTip.getParent() != this) {
add(myToolTip);
repaint();
}
else if (!text.equals(oldText)) {
myToolTip.repaint();
}
}
}
public void removeFeedback() {
boolean needRepaint = false;
if (myFeedbackPainterPanel.getParent() == this) {
remove(myFeedbackPainterPanel);
needRepaint = true;
}
if (myToolTip.getParent() == this) {
remove(myToolTip);
needRepaint = true;
}
if (needRepaint) repaint();
}
private static class RectangleFeedbackPainter implements FeedbackPainter {
public void paintFeedback(Graphics2D g2d, Rectangle rc) {
g2d.setColor(PlatformColors.BLUE);
g2d.setStroke(new BasicStroke(2.5f));
// give space for stroke to be painted
g2d.drawRect(rc.x+1, rc.y+1, rc.x+rc.width-2, rc.y+rc.height-2);
}
}
private static class FeedbackPainterPanel extends JPanel {
private FeedbackPainter myFeedbackPainter;
public FeedbackPainterPanel() {
setOpaque(false);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
final Stroke savedStroke = g2d.getStroke();
final Color savedColor = g2d.getColor();
try {
myFeedbackPainter.paintFeedback(g2d, new Rectangle(0, 0, getWidth(), getHeight()));
}
finally {
g2d.setStroke(savedStroke);
g2d.setColor(savedColor);
}
}
public void setPainter(final FeedbackPainter feedbackPainter) {
myFeedbackPainter = feedbackPainter;
}
}
private class MyNavigateButtonSelectionWatcher extends SelectionWatcher {
public MyNavigateButtonSelectionWatcher(final GuiEditor editor) {
super(editor);
}
protected void selectionChanged(RadComponent component, boolean selected) {
ListenerNavigateButton btn = myNavigateButtons.get(component);
if (selected) {
DefaultActionGroup group = component.getBinding() != null ? ListenerNavigateButton.prepareActionGroup(component) : null;
if (group != null && group.getChildrenCount() > 0) {
if (btn == null) {
btn = new ListenerNavigateButton(component);
myNavigateButtons.put(component, btn);
}
add(btn);
btn.setVisible(true);
}
else {
if (btn != null) {
btn.setVisible(false);
}
}
}
else {
if (btn != null) {
btn.setVisible(false);
}
}
}
}
}