blob: be3912f59ec3d09a272f45c9bb095ab28c9d2b0e [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.openapi.wm.impl.status;
import com.intellij.ide.ClipboardSynchronizer;
import com.intellij.notification.EventLog;
import com.intellij.notification.Notification;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.ui.JBMenuItem;
import com.intellij.openapi.ui.JBPopupMenu;
import com.intellij.openapi.util.Trinity;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.ui.ClickListener;
import com.intellij.ui.JBColor;
import com.intellij.util.Alarm;
import com.intellij.util.text.DateFormatUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
/**
* @author peter
*/
class StatusPanel extends JPanel {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.impl.status.StatusPanel");
private Notification myCurrentNotification;
private int myTimeStart;
private boolean myDirty;
private boolean myAfterClick;
private Alarm myLogAlarm;
private final Action myCopyAction;
private final TextPanel myTextPanel = new TextPanel() {
@Override
protected String getTextForPreferredSize() {
return getText();
}
@Override
public void setBounds(int x, int y, int w, int h) {
super.setBounds(x, y, Math.min(w, StatusPanel.this.getWidth()), h);
}
@Override
protected String truncateText(String text, Rectangle bounds, FontMetrics fm, Rectangle textR, Rectangle iconR, int maxWidth) {
if (myTimeStart > 0) {
if (myTimeStart >= text.length()) {
LOG.error(myTimeStart + " " + text.length());
}
final String time = text.substring(myTimeStart);
final int withoutTime = maxWidth - fm.stringWidth(time);
int end = Math.min(myTimeStart - 1, 1000);
while (end > 0) {
final String truncated = text.substring(0, end) + "... ";
if (fm.stringWidth(truncated) < withoutTime) {
text = truncated + time;
break;
}
end--;
}
}
return super.truncateText(text, bounds, fm, textR, iconR, maxWidth);
}
};
StatusPanel() {
super(new BorderLayout());
setOpaque(false);
myTextPanel.setBorder(new EmptyBorder(0, 5, 0, 0));
new ClickListener() {
@Override
public boolean onClick(@NotNull MouseEvent e, int clickCount) {
if (myCurrentNotification != null || myAfterClick) {
EventLog.toggleLog(getActiveProject(), myCurrentNotification);
myAfterClick = true;
myTextPanel.setExplicitSize(myTextPanel.getSize());
myTextPanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
}
return true;
}
}.installOn(myTextPanel);
myCopyAction = createCopyAction();
myTextPanel.addMouseListener(new MouseAdapter() {
@Override
public void mouseExited(MouseEvent e) {
myTextPanel.setExplicitSize(null);
myTextPanel.revalidate();
myAfterClick = false;
if (myCurrentNotification == null) {
myTextPanel.setCursor(Cursor.getDefaultCursor());
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (myCopyAction != null && e.isPopupTrigger()) {
JBPopupMenu menu = new JBPopupMenu();
menu.add(new JBMenuItem(myCopyAction));
menu.show(myTextPanel, e.getX(), e.getY());
}
}
});
add(myTextPanel, BorderLayout.WEST);
JPanel panel = new JPanel();
panel.setOpaque(isOpaque());
JLabel label = new JLabel("aaa");
label.setBackground(JBColor.YELLOW);
add(panel, BorderLayout.CENTER);
}
private Action createCopyAction() {
ActionManager actionManager = ActionManager.getInstance();
if (actionManager == null) return null;
AnAction action = actionManager.getAction(IdeActions.ACTION_COPY);
if (action == null) return null;
return new AbstractAction(action.getTemplatePresentation().getText(), action.getTemplatePresentation().getIcon()) {
@Override
public void actionPerformed(ActionEvent e) {
StringSelection content = new StringSelection(getText());
ClipboardSynchronizer.getInstance().setContent(content, content);
}
@Override
public boolean isEnabled() {
return !getText().isEmpty();
}
};
}
@Nullable
private Project getActiveProject() {
// a better way of finding a project would be great
for (Project project : ProjectManager.getInstance().getOpenProjects()) {
IdeFrame ideFrame = WindowManager.getInstance().getIdeFrame(project);
if (ideFrame != null) {
final JComponent frame = ideFrame.getComponent();
if (SwingUtilities.isDescendingFrom(myTextPanel, frame)) {
return project;
}
}
}
return null;
}
// Returns the alarm used for displaying status messages in the status bar, or null if the status bar is attached to a floating
// editor window.
@Nullable
private Alarm getAlarm() {
if (myLogAlarm == null || myLogAlarm.isDisposed()) {
myLogAlarm = null; //Welcome screen
Project project = getActiveProject();
if (project != null) {
myLogAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD, project);
}
}
return myLogAlarm;
}
public boolean updateText(@Nullable String nonLogText) {
ApplicationManager.getApplication().assertIsDispatchThread();
final Project project = getActiveProject();
final Trinity<Notification, String, Long> statusMessage = EventLog.getStatusMessage(project);
final Alarm alarm = getAlarm();
myCurrentNotification = StringUtil.isEmpty(nonLogText) && statusMessage != null && alarm != null ? statusMessage.first : null;
if (alarm != null) {
alarm.cancelAllRequests();
}
if (myCurrentNotification != null) {
myTextPanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
new Runnable() {
@Override
public void run() {
assert statusMessage != null;
String text = statusMessage.second;
if (myDirty || System.currentTimeMillis() - statusMessage.third >= DateFormatUtil.MINUTE) {
myTimeStart = text.length() + 1;
text += " (" + StringUtil.decapitalize(DateFormatUtil.formatPrettyDateTime(statusMessage.third)) + ")";
} else {
myTimeStart = -1;
}
setStatusText(text);
alarm.addRequest(this, 30000);
}
}.run();
}
else {
myTimeStart = -1;
myTextPanel.setCursor(Cursor.getDefaultCursor());
myDirty = true;
setStatusText(nonLogText);
}
return myCurrentNotification != null;
}
private void setStatusText(String text) {
myTextPanel.setText(text);
if (!myAfterClick) {
myTextPanel.revalidate();
}
}
public String getText() {
return myTextPanel.getText();
}
}