VCS: asynch load of committed changes when do "Browse changes"
[fedora-idea.git] / platform / vcs-impl / src / com / intellij / openapi / vcs / changes / committed / ColumnFilteringStrategy.java
blob5b8c4095956a40ebe2bfbb499e63f5d7861cefc2
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.openapi.vcs.changes.committed;
18 import com.intellij.openapi.vcs.ChangeListColumn;
19 import com.intellij.openapi.vcs.CommittedChangesProvider;
20 import com.intellij.openapi.vcs.VcsBundle;
21 import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
22 import com.intellij.ui.ColoredListCellRenderer;
23 import com.intellij.ui.SimpleTextAttributes;
24 import com.intellij.util.ArrayUtil;
25 import com.intellij.util.containers.ContainerUtil;
26 import com.intellij.util.containers.Convertor;
27 import org.jetbrains.annotations.NotNull;
28 import org.jetbrains.annotations.Nullable;
30 import javax.swing.*;
31 import javax.swing.event.ChangeEvent;
32 import javax.swing.event.ChangeListener;
33 import javax.swing.event.ListSelectionEvent;
34 import javax.swing.event.ListSelectionListener;
35 import java.awt.*;
36 import java.util.*;
37 import java.util.List;
38 import java.util.concurrent.CopyOnWriteArrayList;
40 /**
41 * @author yole
43 public class ColumnFilteringStrategy extends JPanel implements ChangeListFilteringStrategy {
44 private final JList myValueList;
45 private final CopyOnWriteArrayList<ChangeListener> myListeners = ContainerUtil.createEmptyCOWList();
46 private final ChangeListColumn myColumn;
47 private final Class<? extends CommittedChangesProvider> myProviderClass;
48 private final MyListModel myModel;
49 private final CommittedChangeListToStringConvertor ourConvertorInstance = new CommittedChangeListToStringConvertor();
51 private Object[] myPrefferedSelection;
53 public ColumnFilteringStrategy(final ChangeListColumn column,
54 final Class<? extends CommittedChangesProvider> providerClass) {
55 setLayout(new BorderLayout());
56 myModel = new MyListModel();
57 myValueList = new JList();
58 add(new JScrollPane(myValueList));
59 myValueList.setModel(myModel);
60 myValueList.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
61 public void valueChanged(final ListSelectionEvent e) {
62 for(ChangeListener listener: myListeners) {
63 listener.stateChanged(new ChangeEvent(this));
66 });
67 myValueList.setCellRenderer(new ColoredListCellRenderer() {
68 protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) {
69 if (index == 0) {
70 append(value.toString(), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
72 else if (value.toString().length() == 0) {
73 append(VcsBundle.message("committed.changes.filter.none"), SimpleTextAttributes.GRAYED_ATTRIBUTES);
75 else {
76 append(value.toString(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
79 });
80 myColumn = column;
81 myProviderClass = providerClass;
84 public String toString() {
85 return myColumn.getTitle();
88 @Override
89 public Dimension getPreferredSize() {
90 return new Dimension(100, 100);
93 @Nullable
94 public JComponent getFilterUI() {
95 return this;
98 public void setFilterBase(List<CommittedChangeList> changeLists) {
99 myPrefferedSelection = null;
100 appendFilterBase(changeLists);
103 public void addChangeListener(final ChangeListener listener) {
104 myListeners.add(listener);
107 public void removeChangeListener(final ChangeListener listener) {
108 myListeners.remove(listener);
111 public void resetFilterBase() {
112 myPrefferedSelection = myValueList.getSelectedValues();
113 myValueList.clearSelection();
114 myModel.clear();
115 myValueList.revalidate();
116 myValueList.repaint();
119 public void appendFilterBase(List<CommittedChangeList> changeLists) {
120 final Object[] oldSelection = myModel.isEmpty() ? myPrefferedSelection : myValueList.getSelectedValues();
122 myModel.addNext(changeLists, ourConvertorInstance);
123 if (oldSelection != null) {
124 for (Object o : oldSelection) {
125 myValueList.setSelectedValue(o, false);
128 myValueList.revalidate();
129 myValueList.repaint();
132 private class CommittedChangeListToStringConvertor implements Convertor<CommittedChangeList, String> {
133 public String convert(CommittedChangeList o) {
134 if (myProviderClass == null || myProviderClass.isInstance(o.getVcs().getCommittedChangesProvider())) {
135 return myColumn.getValue(ReceivedChangeList.unwrap(o)).toString();
137 return null;
141 @NotNull
142 public List<CommittedChangeList> filterChangeLists(List<CommittedChangeList> changeLists) {
143 final Object[] selection = myValueList.getSelectedValues();
144 if (myValueList.getSelectedIndex() == 0 || selection.length == 0) {
145 return changeLists;
147 List<CommittedChangeList> result = new ArrayList<CommittedChangeList>();
148 for(CommittedChangeList changeList: changeLists) {
149 if (myProviderClass == null || myProviderClass.isInstance(changeList.getVcs().getCommittedChangesProvider())) {
150 for(Object value: selection) {
151 //noinspection unchecked
152 if (value.toString().equals(myColumn.getValue(ReceivedChangeList.unwrap(changeList)).toString())) {
153 result.add(changeList);
154 break;
159 return result;
162 private static class MyListModel extends AbstractListModel {
163 private volatile String[] myValues;
165 private MyListModel() {
166 myValues = ArrayUtil.EMPTY_STRING_ARRAY;
169 public<T> void addNext(final Collection<T> values, final Convertor<T, String> convertor) {
170 final TreeSet<String> set = new TreeSet<String>(Arrays.asList(myValues));
171 for (T value : values) {
172 final String converted = convertor.convert(value);
173 if (converted != null) {
174 // also works as filter
175 set.add(converted);
178 myValues = ArrayUtil.toStringArray(set);
181 public int getSize() {
182 return myValues.length + 1;
185 public boolean isEmpty() {
186 return myValues.length == 0;
189 public Object getElementAt(int index) {
190 if (index == 0) {
191 return VcsBundle.message("committed.changes.filter.all");
193 return myValues[index-1];
196 public void clear() {
197 myValues = ArrayUtil.EMPTY_STRING_ARRAY;