blob: 6d14c60faa48b502f16509525e0fdc2e1f5bc0ab [file] [log] [blame]
/*
* Copyright 2000-2010 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.ui.components;
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.NotNullFunction;
import com.intellij.util.ui.AsyncProcessIcon;
import com.intellij.util.ui.ComponentWithEmptyText;
import com.intellij.util.ui.StatusText;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.Collection;
/**
* @author Anton Makeev
* @author Konstantin Bulenkov
*/
public class JBList extends JList implements ComponentWithEmptyText, ComponentWithExpandableItems<Integer>{
@NotNull private StatusText myEmptyText;
@NotNull private ExpandableItemsHandler<Integer> myExpandableItemsHandler;
@Nullable private AsyncProcessIcon myBusyIcon;
private boolean myBusy;
public JBList() {
init();
}
public JBList(@NotNull ListModel dataModel) {
super(dataModel);
init();
}
public JBList(@NotNull Object... listData) {
super(createDefaultListModel(listData));
init();
}
@NotNull
public static DefaultListModel createDefaultListModel(@NotNull Object... items) {
final DefaultListModel model = new DefaultListModel();
for (Object item : items) {
model.add(model.getSize(), item);
}
return model;
}
public JBList(@NotNull Collection items) {
this(ArrayUtil.toObjectArray(items));
}
@Override
public void removeNotify() {
super.removeNotify();
if (!ScreenUtil.isStandardAddRemoveNotify(this))
return;
if (myBusyIcon != null) {
remove(myBusyIcon);
Disposer.dispose(myBusyIcon);
myBusyIcon = null;
}
}
@Override
public void doLayout() {
super.doLayout();
if (myBusyIcon != null) {
myBusyIcon.updateLocation(this);
}
}
@Override
public void paint(Graphics g) {
super.paint(g);
if (myBusyIcon != null) {
myBusyIcon.updateLocation(this);
}
}
public void setPaintBusy(boolean paintBusy) {
if (myBusy == paintBusy) return;
myBusy = paintBusy;
updateBusy();
}
private void updateBusy() {
if (myBusy) {
if (myBusyIcon == null) {
myBusyIcon = new AsyncProcessIcon(toString()).setUseMask(false);
myBusyIcon.setOpaque(false);
myBusyIcon.setPaintPassiveIcon(false);
add(myBusyIcon);
}
}
if (myBusyIcon != null) {
if (myBusy) {
myBusyIcon.resume();
}
else {
myBusyIcon.suspend();
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
public void run() {
if (myBusyIcon != null) {
repaint();
}
}
});
}
if (myBusyIcon != null) {
myBusyIcon.updateLocation(this);
}
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
myEmptyText.paint(this, g);
}
@Override
public Dimension getPreferredSize() {
if (getModel().getSize() == 0 && !StringUtil.isEmpty(getEmptyText().getText())) {
Dimension s = getEmptyText().getPreferredSize();
Insets insets = getInsets();
if (insets != null) {
s.width += (insets.left + insets.right);
s.height += (insets.top + insets.bottom);
}
return s;
} else {
return super.getPreferredSize();
}
}
private void init() {
setSelectionBackground(UIUtil.getListSelectionBackground());
setSelectionForeground(UIUtil.getListSelectionForeground());
myEmptyText = new StatusText(this) {
@Override
protected boolean isStatusVisible() {
return JBList.this.isEmpty();
}
};
myExpandableItemsHandler = ExpandableItemsHandlerFactory.install(this);
setCellRenderer(new DefaultListCellRenderer());
}
public boolean isEmpty() {
return getItemsCount() == 0;
}
public int getItemsCount() {
ListModel model = getModel();
return model == null ? 0 : model.getSize();
}
@NotNull
@Override
public StatusText getEmptyText() {
return myEmptyText;
}
public void setEmptyText(@NotNull String text) {
myEmptyText.setText(text);
}
@Override
@NotNull
public ExpandableItemsHandler<Integer> getExpandableItemsHandler() {
return myExpandableItemsHandler;
}
@Override
public void setExpandableItemsEnabled(boolean enabled) {
myExpandableItemsHandler.setEnabled(enabled);
}
@Override
public void setCellRenderer(final ListCellRenderer cellRenderer) {
// myExpandableItemsHandler may not yeb be initialized
//noinspection ConstantConditions
if (myExpandableItemsHandler == null) {
super.setCellRenderer(cellRenderer);
return;
}
super.setCellRenderer(new ExpandedItemListCellRendererWrapper(cellRenderer, myExpandableItemsHandler));
}
public <T> void installCellRenderer(@NotNull final NotNullFunction<T, JComponent> fun) {
setCellRenderer(new DefaultListCellRenderer() {
@NotNull
@Override
public Component getListCellRendererComponent(@NotNull JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus) {
@SuppressWarnings({"unchecked"})
final JComponent comp = fun.fun((T)value);
comp.setOpaque(true);
if (isSelected) {
comp.setBackground(list.getSelectionBackground());
comp.setForeground(list.getSelectionForeground());
}
else {
comp.setBackground(list.getBackground());
comp.setForeground(list.getForeground());
}
for (JLabel label : UIUtil.findComponentsOfType(comp, JLabel.class)) {
label.setForeground(UIUtil.getListForeground(isSelected));
}
return comp;
}
});
}
public void setDataProvider(@NotNull DataProvider provider) {
DataManager.registerDataProvider(this, provider);
}
public void disableEmptyText() {
getEmptyText().setText("");
}
public static class StripedListCellRenderer extends DefaultListCellRenderer {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (!isSelected && index % 2 == 0) {
setBackground(UIUtil.getDecoratedRowColor());
}
return this;
}
}
}