| /* |
| * 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; |
| } |
| } |
| } |