blob: cd4dbfc03b61268798347a89fe2eca56ed4af484 [file] [log] [blame]
/*
* Copyright 2000-2009 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.vcs.changes.committed;
import com.intellij.openapi.vcs.ChangeListColumn;
import com.intellij.openapi.vcs.CommittedChangesProvider;
import com.intellij.openapi.vcs.VcsBundle;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
import com.intellij.ui.ColoredListCellRenderer;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.ui.components.JBList;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Convertor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.util.*;
/**
* @author yole
*/
public class ColumnFilteringStrategy implements ChangeListFilteringStrategy {
private final JScrollPane myScrollPane;
private final JList myValueList;
private final List<ChangeListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
private final ChangeListColumn myColumn;
private final Class<? extends CommittedChangesProvider> myProviderClass;
private final MyListModel myModel;
private final CommittedChangeListToStringConvertor ourConvertorInstance = new CommittedChangeListToStringConvertor();
private Object[] myPrefferedSelection;
public ColumnFilteringStrategy(final ChangeListColumn column,
final Class<? extends CommittedChangesProvider> providerClass) {
myModel = new MyListModel();
myValueList = new JBList();
myScrollPane = ScrollPaneFactory.createScrollPane(myValueList);
myValueList.setModel(myModel);
myValueList.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
public void valueChanged(final ListSelectionEvent e) {
for (ChangeListener listener : myListeners) {
listener.stateChanged(new ChangeEvent(this));
}
}
});
myValueList.setCellRenderer(new ColoredListCellRenderer() {
protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) {
if (index == 0) {
append(value.toString(), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
}
else if (value.toString().length() == 0) {
append(VcsBundle.message("committed.changes.filter.none"), SimpleTextAttributes.GRAYED_ATTRIBUTES);
}
else {
append(value.toString(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
}
}
});
myColumn = column;
myProviderClass = providerClass;
}
@Override
public CommittedChangesFilterKey getKey() {
return new CommittedChangesFilterKey(toString(), CommittedChangesFilterPriority.USER);
}
public String toString() {
return myColumn.getTitle();
}
@Nullable
public JComponent getFilterUI() {
return myScrollPane;
}
public void setFilterBase(List<CommittedChangeList> changeLists) {
myPrefferedSelection = null;
appendFilterBase(changeLists);
}
public void addChangeListener(final ChangeListener listener) {
myListeners.add(listener);
}
public void removeChangeListener(final ChangeListener listener) {
myListeners.remove(listener);
}
public void resetFilterBase() {
myPrefferedSelection = myValueList.getSelectedValues();
myValueList.clearSelection();
myModel.clear();
myValueList.revalidate();
myValueList.repaint();
}
public void appendFilterBase(List<CommittedChangeList> changeLists) {
final Object[] oldSelection = myModel.isEmpty() ? myPrefferedSelection : myValueList.getSelectedValues();
myModel.addNext(changeLists, ourConvertorInstance);
if (oldSelection != null) {
for (Object o : oldSelection) {
myValueList.setSelectedValue(o, false);
}
}
myValueList.revalidate();
myValueList.repaint();
}
private class CommittedChangeListToStringConvertor implements Convertor<CommittedChangeList, String> {
public String convert(CommittedChangeList o) {
if (myProviderClass == null || myProviderClass.isInstance(o.getVcs().getCommittedChangesProvider())) {
return myColumn.getValue(ReceivedChangeList.unwrap(o)).toString();
}
return null;
}
}
@NotNull
public List<CommittedChangeList> filterChangeLists(List<CommittedChangeList> changeLists) {
final Object[] selection = myValueList.getSelectedValues();
if (myValueList.getSelectedIndex() == 0 || selection.length == 0) {
return changeLists;
}
List<CommittedChangeList> result = new ArrayList<CommittedChangeList>();
for (CommittedChangeList changeList : changeLists) {
if (myProviderClass == null || myProviderClass.isInstance(changeList.getVcs().getCommittedChangesProvider())) {
for (Object value : selection) {
//noinspection unchecked
if (value.toString().equals(myColumn.getValue(ReceivedChangeList.unwrap(changeList)).toString())) {
result.add(changeList);
break;
}
}
}
}
return result;
}
private static class MyListModel extends AbstractListModel {
private volatile String[] myValues;
private MyListModel() {
myValues = ArrayUtil.EMPTY_STRING_ARRAY;
}
public <T> void addNext(final Collection<T> values, final Convertor<T, String> convertor) {
final TreeSet<String> set = new TreeSet<String>(Arrays.asList(myValues));
for (T value : values) {
final String converted = convertor.convert(value);
if (converted != null) {
// also works as filter
set.add(converted);
}
}
myValues = ArrayUtil.toStringArray(set);
fireContentsChanged(this, 0, myValues.length);
}
public int getSize() {
return myValues.length + 1;
}
public boolean isEmpty() {
return myValues.length == 0;
}
public Object getElementAt(int index) {
if (index == 0) {
return VcsBundle.message("committed.changes.filter.all");
}
return myValues[index - 1];
}
public void clear() {
myValues = ArrayUtil.EMPTY_STRING_ARRAY;
}
}
}