blob: d358e86c2a40f3125e82965b7fcc4992a2a65f6a [file] [log] [blame]
/*
* Copyright 2000-2013 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.vcs.log.ui.filter;
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.vcs.log.*;
import com.intellij.vcs.log.data.DataPack;
import com.intellij.vcs.log.data.VcsLogBranchFilterImpl;
import com.intellij.vcs.log.data.VcsLogUiProperties;
import com.intellij.vcs.log.impl.VcsLogUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
public class BranchFilterPopupComponent extends MultipleValueFilterPopupComponent<VcsLogBranchFilter> {
@NotNull private final VcsLogUiProperties myUiProperties;
@NotNull private VcsLogDataPack myDataPack;
public BranchFilterPopupComponent(@NotNull VcsLogClassicFilterUi filterUi, @NotNull VcsLogDataPack dataPack,
@NotNull VcsLogUiProperties uiProperties) {
super(filterUi, "Branch");
myDataPack = dataPack;
myUiProperties = uiProperties;
}
void updateDataPack(@NotNull DataPack dataPack) {
myDataPack = dataPack;
}
@Override
protected ActionGroup createActionGroup() {
DefaultActionGroup actionGroup = new DefaultActionGroup();
actionGroup.add(createAllAction());
actionGroup.add(createSelectMultipleValuesAction());
actionGroup.add(constructActionGroup(myDataPack, createRecentItemsActionGroup(), new Function<String, AnAction>() {
@Override
public AnAction fun(String name) {
return createPredefinedValueAction(Collections.singleton(name));
}
}));
return actionGroup;
}
public static ActionGroup constructActionGroup(@NotNull VcsLogDataPack dataPack, @Nullable ActionGroup recentItemsGroup,
@NotNull Function<String, AnAction> actionGetter) {
Groups groups = prepareGroups(dataPack);
return getFilteredActionGroup(groups, recentItemsGroup, actionGetter);
}
private static Groups prepareGroups(@NotNull VcsLogDataPack dataPack) {
Groups filteredGroups = new Groups();
Collection<VcsRef> allRefs = dataPack.getRefs().getBranches();
for (Map.Entry<VirtualFile, Collection<VcsRef>> entry : VcsLogUtil.groupRefsByRoot(allRefs).entrySet()) {
VirtualFile root = entry.getKey();
Collection<VcsRef> refs = entry.getValue();
VcsLogProvider provider = dataPack.getLogProviders().get(root);
VcsLogRefManager refManager = provider.getReferenceManager();
List<RefGroup> refGroups = refManager.group(refs);
orderRefGroups(refGroups, filteredGroups);
}
return filteredGroups;
}
private static DefaultActionGroup getFilteredActionGroup(@NotNull Groups groups, @Nullable ActionGroup recentItems,
@NotNull Function<String, AnAction> actionGetter) {
DefaultActionGroup actionGroup = new DefaultActionGroup();
for (String single : groups.singletonGroups) {
actionGroup.add(actionGetter.fun(single));
}
if (recentItems != null) {
actionGroup.add(recentItems);
}
for (Map.Entry<String, TreeSet<String>> group : groups.expandedGroups.entrySet()) {
actionGroup.addSeparator(group.getKey());
for (String action : group.getValue()) {
actionGroup.add(actionGetter.fun(action));
}
}
actionGroup.addSeparator();
for (Map.Entry<String, TreeSet<String>> group : groups.collapsedGroups.entrySet()) {
DefaultActionGroup popupGroup = new DefaultActionGroup(group.getKey(), true);
for (String action : group.getValue()) {
popupGroup.add(actionGetter.fun(action));
}
actionGroup.add(popupGroup);
}
return actionGroup;
}
private static class Groups {
private final TreeSet<String> singletonGroups = ContainerUtil.newTreeSet();
private final TreeMap<String, TreeSet<String>> expandedGroups = ContainerUtil.newTreeMap();
private final TreeMap<String, TreeSet<String>> collapsedGroups = ContainerUtil.newTreeMap();
}
private static void orderRefGroups(List<RefGroup> groups, Groups filteredGroups) {
for (final RefGroup group : groups) {
if (group.getRefs().size() == 1) {
String name = group.getRefs().iterator().next().getName();
if (!filteredGroups.singletonGroups.contains(name)) {
filteredGroups.singletonGroups.add(name);
}
}
else if (group.isExpanded()) {
addToGroup(group, filteredGroups.expandedGroups);
}
else {
addToGroup(group, filteredGroups.collapsedGroups);
}
}
}
private static void addToGroup(final RefGroup group, TreeMap<String, TreeSet<String>> groupToAdd) {
TreeSet<String> existingGroup = groupToAdd.get(group.getName());
TreeSet<String> actions = new TreeSet<String>();
for (VcsRef ref : group.getRefs()) {
actions.add(ref.getName());
}
if (existingGroup == null) {
groupToAdd.put(group.getName(), actions);
}
else {
for (String action : actions) {
existingGroup.add(action);
}
}
}
@Nullable
@Override
protected VcsLogBranchFilter getFilter() {
if (getSelectedValues() == null) {
return null;
}
return new VcsLogBranchFilterImpl(getSelectedValues());
}
@NotNull
@Override
protected List<List<String>> getRecentValuesFromSettings() {
return myUiProperties.getRecentlyFilteredBranchGroups();
}
@Override
protected void rememberValuesInSettings(@NotNull Collection<String> values) {
if (values.size() > 1) { // all branches are in the popup => no need to save single one, only in case of multiple selection
myUiProperties.addRecentlyFilteredBranchGroup(new ArrayList<String>(values));
}
}
@NotNull
@Override
protected List<String> getAllValues() {
return ContainerUtil.map(myDataPack.getRefs().getBranches(), new Function<VcsRef, String>() {
@Override
public String fun(VcsRef ref) {
return ref.getName();
}
});
}
}