blob: 479b968d43171c608194bf849add1923bb5c7e84 [file] [log] [blame]
/*
* Copyright 2000-2013 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.util.ui;
import com.intellij.ui.ClickListener;
import com.intellij.ui.SimpleColoredComponent;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.ui.UIBundle;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;
public abstract class StatusText {
public static final SimpleTextAttributes DEFAULT_ATTRIBUTES = SimpleTextAttributes.GRAYED_ATTRIBUTES;
public static final String DEFAULT_EMPTY_TEXT = UIBundle.message("message.nothingToShow");
@Nullable
private Component myOwner;
private Component myMouseTarget;
private final MouseMotionListener myMouseMotionListener;
private final ClickListener myClickListener;
private boolean myIsDefaultText;
private String myText = "";
protected final SimpleColoredComponent myComponent = new SimpleColoredComponent();
private final List<ActionListener> myClickListeners = new ArrayList<ActionListener>();
private boolean myHasActiveClickListeners; // calculated field for performance optimization
protected StatusText(JComponent owner) {
this();
attachTo(owner);
}
public StatusText() {
myClickListener = new ClickListener() {
@Override
public boolean onClick(@NotNull MouseEvent e, int clickCount) {
if (e.getButton() == MouseEvent.BUTTON1 && clickCount == 1) {
ActionListener actionListener = findActionListenerAt(e.getPoint());
if (actionListener != null) {
actionListener.actionPerformed(new ActionEvent(this, 0, ""));
return true;
}
}
return false;
}
};
myMouseMotionListener = new MouseAdapter() {
private Cursor myOriginalCursor;
@Override
public void mouseMoved(final MouseEvent e) {
if (isStatusVisible()) {
if (findActionListenerAt(e.getPoint()) != null) {
if (myOriginalCursor == null) {
myOriginalCursor = myMouseTarget.getCursor();
myMouseTarget.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
}
}
else if (myOriginalCursor != null) {
myMouseTarget.setCursor(myOriginalCursor);
myOriginalCursor = null;
}
}
}
};
myComponent.setOpaque(false);
myComponent.setFont(UIUtil.getLabelFont());
setText(DEFAULT_EMPTY_TEXT, DEFAULT_ATTRIBUTES);
myIsDefaultText = true;
}
public void attachTo(@Nullable Component owner) {
attachTo(owner, owner);
}
public void attachTo(@Nullable Component owner, @Nullable Component mouseTarget) {
if (myMouseTarget != null) {
myClickListener.uninstall(myMouseTarget);
myMouseTarget.removeMouseMotionListener(myMouseMotionListener);
}
myOwner = owner;
myMouseTarget = mouseTarget;
if (myMouseTarget != null) {
myClickListener.installOn(myMouseTarget);
myMouseTarget.addMouseMotionListener(myMouseMotionListener);
}
}
protected abstract boolean isStatusVisible();
@Nullable
private ActionListener findActionListenerAt(Point point) {
if (!myHasActiveClickListeners || !isStatusVisible()) return null;
point = SwingUtilities.convertPoint(myMouseTarget, point, myOwner);
Rectangle b = getTextComponentBound();
if (b.contains(point)) {
int index = myComponent.findFragmentAt(point.x - b.x);
if (index >= 0 && index < myClickListeners.size()) {
return myClickListeners.get(index);
}
}
return null;
}
protected Rectangle getTextComponentBound() {
Rectangle ownerRec = myOwner == null ? new Rectangle(0, 0, 0, 0) : myOwner.getBounds();
Dimension size = myComponent.getPreferredSize();
int x = (ownerRec.width - size.width) / 2;
int y = (ownerRec.height - size.height) / 3;
return new Rectangle(x, y, size.width, size.height);
}
@NotNull
public String getText() {
return myText;
}
public StatusText setText(String text) {
return setText(text, DEFAULT_ATTRIBUTES);
}
public StatusText setText(String text, SimpleTextAttributes attrs) {
return clear().appendText(text, attrs);
}
public StatusText clear() {
myText = "";
myComponent.clear();
myClickListeners.clear();
myHasActiveClickListeners = false;
if (myOwner != null) myOwner.repaint();
return this;
}
public StatusText appendText(String text) {
return appendText(text, DEFAULT_ATTRIBUTES);
}
public StatusText appendText(String text, SimpleTextAttributes attrs) {
return appendText(text, attrs, null);
}
public StatusText appendText(String text, SimpleTextAttributes attrs, ActionListener listener) {
if (myIsDefaultText) {
clear();
myIsDefaultText = false;
}
myText += text;
myComponent.append(text, attrs);
myClickListeners.add(listener);
if (listener != null) {
myHasActiveClickListeners = true;
}
if (myOwner != null) myOwner.repaint();
return this;
}
public void paint(Component owner, Graphics g) {
boolean wrongComponent = owner != myOwner && owner != null && owner.getParent() != myOwner;
if (!isStatusVisible() || wrongComponent) return;
Rectangle b = getTextComponentBound();
myComponent.setBounds(0, 0, b.width, b.height);
Graphics2D g2 = (Graphics2D)g.create(b.x, b.y, b.width, b.height);
myComponent.paint(g2);
g2.dispose();
}
@NotNull
public SimpleColoredComponent getComponent() {
return myComponent;
}
public Dimension getPreferredSize() {
return myComponent.getPreferredSize();
}
}