From bd5bb3c84a8ff37102532b743beddf8e00c80af3 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Thu, 20 Dec 2018 00:26:38 +0300 Subject: [PATCH] [vcs-log] properly support working with filter pairs in filter models Some filter models work with several filters simultaneously, for example FileFilterModel sets both structure and root filters, and TextFilterModel works with text and hash filters. For FileFilterModel a special composite filter class, VcsLogFileFilter, was used. It implemented VcsLogFilter interface, but was not actually a filter, which was confusing. On the other hand, TextFilterModel did not have a special filter class and just secretly created a hash filter. In order to unify working with such models, FilterPair class is introduced, and a descendant of FilterModel for working with filter pairs is extracted. Both FileFilterModel and TextFilterModel are adjusted to work with FilterPair. --- .../vcs/log/VcsLogFilterCollection.java | 18 +- .../ui/filter/BranchFilterPopupComponent.java | 19 +- .../ui/filter/DateFilterPopupComponent.java | 18 +- .../vcs/log/ui/filter/FilterModel.java | 166 +++++++++++---- .../log/ui/filter/FilterPopupComponent.java | 23 +-- .../MultipleValueFilterPopupComponent.java | 21 +- .../filter/StructureFilterPopupComponent.java | 80 ++++---- .../ui/filter/UserFilterPopupComponent.java | 23 +-- .../log/ui/filter/VcsLogClassicFilterUi.java | 194 ++++++++---------- .../vcs/log/visible/filters/FilterPair.kt | 6 + .../log/visible/filters/VcsLogFileFilter.java | 52 ----- 11 files changed, 277 insertions(+), 343 deletions(-) create mode 100644 platform/vcs-log/impl/src/com/intellij/vcs/log/visible/filters/FilterPair.kt delete mode 100644 platform/vcs-log/impl/src/com/intellij/vcs/log/visible/filters/VcsLogFileFilter.java diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogFilterCollection.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogFilterCollection.java index cb26b43b0979..110f3f5d87b7 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogFilterCollection.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogFilterCollection.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2014 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.vcs.log; import com.intellij.util.containers.ContainerUtil; @@ -36,7 +22,7 @@ public interface VcsLogFilterCollection { FilterKey DATE_FILTER = FilterKey.create("date"); FilterKey TEXT_FILTER = FilterKey.create("text"); FilterKey STRUCTURE_FILTER = FilterKey.create("structure"); - FilterKey ROOT_FILTER = FilterKey.create("root"); + FilterKey ROOT_FILTER = FilterKey.create("roots"); @Nullable T get(@NotNull FilterKey key); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/BranchFilterPopupComponent.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/BranchFilterPopupComponent.java index cb0654640c78..72e1d8f5d758 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/BranchFilterPopupComponent.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/BranchFilterPopupComponent.java @@ -1,18 +1,4 @@ -/* - * 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.vcs.log.ui.filter; import com.intellij.icons.AllIcons; @@ -41,7 +27,8 @@ import java.awt.event.MouseEvent; import java.util.Collection; import java.util.List; -public class BranchFilterPopupComponent extends MultipleValueFilterPopupComponent { +public class BranchFilterPopupComponent + extends MultipleValueFilterPopupComponent { public static final String BRANCH_FILTER_NAME = "Branch"; private final VcsLogClassicFilterUi.BranchFilterModel myBranchFilterModel; diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/DateFilterPopupComponent.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/DateFilterPopupComponent.java index 9fb4116ad6b4..ad5d541c3ab0 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/DateFilterPopupComponent.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/DateFilterPopupComponent.java @@ -1,18 +1,4 @@ -/* - * 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.vcs.log.ui.filter; import com.intellij.openapi.actionSystem.ActionGroup; @@ -31,7 +17,7 @@ import org.jetbrains.annotations.Nullable; import java.util.Calendar; import java.util.Date; -class DateFilterPopupComponent extends FilterPopupComponent { +class DateFilterPopupComponent extends FilterPopupComponent> { DateFilterPopupComponent(FilterModel filterModel) { super("Date", filterModel); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/FilterModel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/FilterModel.java index e8a832f2e833..091a2b1bf288 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/FilterModel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/FilterModel.java @@ -7,72 +7,46 @@ import com.intellij.vcs.log.VcsLogDataPack; import com.intellij.vcs.log.VcsLogFilter; import com.intellij.vcs.log.VcsLogFilterCollection; import com.intellij.vcs.log.impl.MainVcsLogUiProperties; +import com.intellij.vcs.log.visible.filters.FilterPair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.List; -abstract class FilterModel { - @NotNull private final VcsLogFilterCollection.FilterKey myFilterKey; +abstract class FilterModel { @NotNull protected final MainVcsLogUiProperties myUiProperties; @NotNull private final Computable myDataPackProvider; @NotNull private final Collection mySetFilterListeners = ContainerUtil.newArrayList(); - @Nullable private Filter myFilter; + @Nullable protected Filter myFilter; - FilterModel(@NotNull VcsLogFilterCollection.FilterKey filterKey, - @NotNull Computable provider, - @NotNull MainVcsLogUiProperties uiProperties, - @Nullable VcsLogFilterCollection filters) { - myFilterKey = filterKey; + FilterModel(@NotNull Computable provider, + @NotNull MainVcsLogUiProperties uiProperties) { myUiProperties = uiProperties; myDataPackProvider = provider; - - if (filters != null) { - saveFilter(getFilterFromCollection(filters)); - } - } - - @Nullable - protected Filter getFilterFromCollection(@NotNull VcsLogFilterCollection filters) { - return filters.get(myFilterKey); } void setFilter(@Nullable Filter filter) { myFilter = filter; - saveFilter(filter); + saveFilterToProperties(filter); for (Runnable listener : mySetFilterListeners) { listener.run(); } } - protected void saveFilter(@Nullable Filter filter) { - myUiProperties.saveFilterValues(myFilterKey.getName(), filter == null ? null : getFilterValues(filter)); - } - @Nullable Filter getFilter() { if (myFilter == null) { - myFilter = getLastFilter(); + myFilter = getFilterFromProperties(); } return myFilter; } - @Nullable - protected abstract Filter createFilter(@NotNull List values); - - @NotNull - protected abstract List getFilterValues(@NotNull Filter filter); + protected abstract void saveFilterToProperties(@Nullable Filter filter); @Nullable - protected Filter getLastFilter() { - List values = myUiProperties.getFilterValues(myFilterKey.getName()); - if (values != null) { - return createFilter(values); - } - return null; - } + protected abstract Filter getFilterFromProperties(); @NotNull VcsLogDataPack getDataPack() { @@ -82,4 +56,126 @@ abstract class FilterModel { void addSetFilterListener(@NotNull Runnable runnable) { mySetFilterListeners.add(runnable); } + + public static abstract class SingleFilterModel extends FilterModel { + @NotNull private final VcsLogFilterCollection.FilterKey myFilterKey; + + SingleFilterModel(@NotNull VcsLogFilterCollection.FilterKey filterKey, + @NotNull Computable provider, + @NotNull MainVcsLogUiProperties uiProperties, + @Nullable VcsLogFilterCollection filters) { + super(provider, uiProperties); + myFilterKey = filterKey; + + if (filters != null) { + saveFilterToProperties(filters.get(myFilterKey)); + } + } + + @Nullable + protected abstract Filter createFilter(@NotNull List values); + + @NotNull + protected abstract List getFilterValues(@NotNull Filter filter); + + @Override + protected void saveFilterToProperties(@Nullable Filter filter) { + myUiProperties.saveFilterValues(myFilterKey.getName(), filter == null ? null : getFilterValues(filter)); + } + + @Override + @Nullable + protected Filter getFilterFromProperties() { + List values = myUiProperties.getFilterValues(myFilterKey.getName()); + if (values != null) { + return createFilter(values); + } + return null; + } + } + + public static abstract class PairFilterModel + extends FilterModel> { + @NotNull private final VcsLogFilterCollection.FilterKey myFilterKey1; + @NotNull private final VcsLogFilterCollection.FilterKey myFilterKey2; + + PairFilterModel(@NotNull VcsLogFilterCollection.FilterKey filterKey1, + @NotNull VcsLogFilterCollection.FilterKey filterKey2, + @NotNull Computable provider, + @NotNull MainVcsLogUiProperties uiProperties, + @Nullable VcsLogFilterCollection filters) { + super(provider, uiProperties); + myFilterKey1 = filterKey1; + myFilterKey2 = filterKey2; + + if (filters != null) { + Filter1 filter1 = filters.get(myFilterKey1); + Filter2 filter2 = filters.get(myFilterKey2); + FilterPair filter = (filter1 == null && filter2 == null) ? null : new FilterPair<>(filter1, filter2); + saveFilterToProperties(filter); + } + } + + @Override + protected void saveFilterToProperties(@Nullable FilterPair filter) { + if (filter == null || filter.getFilter1() == null) { + myUiProperties.saveFilterValues(myFilterKey1.getName(), null); + } + else { + myUiProperties.saveFilterValues(myFilterKey1.getName(), getFilter1Values(filter.getFilter1())); + } + + if (filter == null || filter.getFilter2() == null) { + myUiProperties.saveFilterValues(myFilterKey2.getName(), null); + } + else { + myUiProperties.saveFilterValues(myFilterKey2.getName(), getFilter2Values(filter.getFilter2())); + } + } + + @Nullable + @Override + protected FilterPair getFilterFromProperties() { + List values1 = myUiProperties.getFilterValues(myFilterKey1.getName()); + Filter1 filter1 = null; + if (values1 != null) { + filter1 = createFilter1(values1); + } + + List values2 = myUiProperties.getFilterValues(myFilterKey2.getName()); + Filter2 filter2 = null; + if (values2 != null) { + filter2 = createFilter2(values2); + } + + if (filter1 == null && filter2 == null) return null; + return new FilterPair<>(filter1, filter2); + } + + @Nullable + public Filter1 getFilter1() { + FilterPair filterPair = getFilter(); + if (filterPair == null) return null; + return filterPair.getFilter1(); + } + + @Nullable + public Filter2 getFilter2() { + FilterPair filterPair = getFilter(); + if (filterPair == null) return null; + return filterPair.getFilter2(); + } + + @NotNull + protected abstract List getFilter1Values(@NotNull Filter1 filter1); + + @NotNull + protected abstract List getFilter2Values(@NotNull Filter2 filter2); + + @Nullable + protected abstract Filter1 createFilter1(@NotNull List values); + + @Nullable + protected abstract Filter2 createFilter2(@NotNull List values); + } } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/FilterPopupComponent.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/FilterPopupComponent.java index 1278e18d4479..e4bdf3d89c4a 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/FilterPopupComponent.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/FilterPopupComponent.java @@ -1,39 +1,24 @@ -/* - * 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.vcs.log.ui.filter; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.project.DumbAwareAction; -import com.intellij.vcs.log.VcsLogFilter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** * Base class for components which allow to set up filter for the VCS Log, by displaying a popup with available choices. */ -abstract class FilterPopupComponent extends VcsLogPopupComponent { +abstract class FilterPopupComponent> extends VcsLogPopupComponent { /** * Special value that indicates that no filtering is on. */ protected static final String ALL = "All"; - @NotNull protected final FilterModel myFilterModel; + @NotNull protected final Model myFilterModel; - FilterPopupComponent(@NotNull String filterName, @NotNull FilterModel filterModel) { + FilterPopupComponent(@NotNull String filterName, @NotNull Model filterModel) { super(filterName); myFilterModel = filterModel; } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/MultipleValueFilterPopupComponent.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/MultipleValueFilterPopupComponent.java index a6ba52e69e36..6169138b9cdb 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/MultipleValueFilterPopupComponent.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/MultipleValueFilterPopupComponent.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2014 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.vcs.log.ui.filter; import com.intellij.openapi.actionSystem.ActionGroup; @@ -34,7 +20,8 @@ import java.util.Collection; import java.util.Collections; import java.util.List; -abstract class MultipleValueFilterPopupComponent extends FilterPopupComponent { +abstract class MultipleValueFilterPopupComponent> + extends FilterPopupComponent { private static final int MAX_FILTER_VALUE_LENGTH = 30; @@ -42,7 +29,7 @@ abstract class MultipleValueFilterPopupComponent ex MultipleValueFilterPopupComponent(@NotNull String filterName, @NotNull MainVcsLogUiProperties uiProperties, - @NotNull FilterModel filterModel) { + @NotNull Model filterModel) { super(filterName, filterModel); myUiProperties = uiProperties; } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/StructureFilterPopupComponent.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/StructureFilterPopupComponent.java index 3dbbe83c934a..55fa9ddd67c8 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/StructureFilterPopupComponent.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/StructureFilterPopupComponent.java @@ -1,18 +1,4 @@ -/* - * 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.vcs.log.ui.filter; import com.intellij.openapi.actionSystem.*; @@ -35,11 +21,11 @@ import com.intellij.vcs.log.VcsLogDataPack; import com.intellij.vcs.log.VcsLogRootFilter; import com.intellij.vcs.log.VcsLogStructureFilter; import com.intellij.vcs.log.impl.MainVcsLogUiProperties; -import com.intellij.vcs.log.visible.filters.VcsLogFileFilter; -import com.intellij.vcs.log.visible.filters.VcsLogFilterObject; import com.intellij.vcs.log.ui.VcsLogColorManager; import com.intellij.vcs.log.ui.table.VcsLogGraphTable; import com.intellij.vcs.log.util.VcsLogUtil; +import com.intellij.vcs.log.visible.filters.FilterPair; +import com.intellij.vcs.log.visible.filters.VcsLogFilterObject; import org.intellij.lang.annotations.JdkConstants; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -51,7 +37,9 @@ import java.awt.event.KeyEvent; import java.util.List; import java.util.*; -class StructureFilterPopupComponent extends FilterPopupComponent { +class StructureFilterPopupComponent extends FilterPopupComponent, + FilterModel.PairFilterModel> { + private static final int FILTER_LABEL_LENGTH = 30; private static final int CHECKBOX_ICON_SIZE = 15; private static final FileByNameComparator FILE_BY_NAME_COMPARATOR = new FileByNameComparator(); @@ -61,21 +49,29 @@ class StructureFilterPopupComponent extends FilterPopupComponent filterModel, + @NotNull FilterModel.PairFilterModel filterModel, @NotNull VcsLogColorManager colorManager) { super("Paths", filterModel); myUiProperties = uiProperties; myColorManager = colorManager; } + private static VcsLogRootFilter getRootFilter(@Nullable FilterPair filter) { + if (filter == null) return null; + return filter.getFilter2(); + } + + private static VcsLogStructureFilter getStructureFilter(@Nullable FilterPair filter) { + if (filter == null) return null; + return filter.getFilter1(); + } + @NotNull @Override - protected String getText(@NotNull VcsLogFileFilter filter) { - Collection roots = filter.getRootFilter() == null ? getAllRoots() : filter.getRootFilter().getRoots(); - Collection files = - filter.getStructureFilter() == null ? Collections.emptySet() : filter.getStructureFilter().getFiles(); - Collection visibleRoots = - VcsLogUtil.getAllVisibleRoots(getAllRoots(), filter.getRootFilter(), filter.getStructureFilter()); + protected String getText(@NotNull FilterPair filter) { + Collection roots = getRootFilter(filter) == null ? getAllRoots() : getRootFilter(filter).getRoots(); + Collection files = getStructureFilter(filter) == null ? Collections.emptySet() : getStructureFilter(filter).getFiles(); + Collection visibleRoots = VcsLogUtil.getAllVisibleRoots(getAllRoots(), getRootFilter(filter), getStructureFilter(filter)); if (files.isEmpty()) { return getTextFromRoots(roots, visibleRoots.size() == getAllRoots().size()); @@ -121,9 +117,9 @@ class StructureFilterPopupComponent extends FilterPopupComponent filter) { + return getToolTip(getRootFilter(filter) == null ? getAllRoots() : getRootFilter(filter).getRoots(), + getStructureFilter(filter) == null ? Collections.emptySet() : getStructureFilter(filter).getFiles()); } @NotNull @@ -201,9 +197,9 @@ class StructureFilterPopupComponent extends FilterPopupComponent filter = myFilterModel.getFilter(); + if (getRootFilter(filter) != null) { + return getRootFilter(filter).getRoots().contains(root); } return true; } @@ -211,8 +207,8 @@ class StructureFilterPopupComponent extends FilterPopupComponent roots = getAllRoots(); - VcsLogFileFilter previousFilter = myFilterModel.getFilter(); - VcsLogRootFilter rootFilter = previousFilter != null ? previousFilter.getRootFilter() : null; + FilterPair previousFilter = myFilterModel.getFilter(); + VcsLogRootFilter rootFilter = getRootFilter(previousFilter); Collection visibleRoots; if (rootFilter == null) { @@ -223,11 +219,11 @@ class StructureFilterPopupComponent extends FilterPopupComponent(rootFilter.getRoots()), Collections.singleton(root)) : ContainerUtil.subtract(rootFilter.getRoots(), Collections.singleton(root)); } - myFilterModel.setFilter(new VcsLogFileFilter(null, VcsLogFilterObject.fromRoots(visibleRoots))); + myFilterModel.setFilter(new FilterPair<>(null, VcsLogFilterObject.fromRoots(visibleRoots))); } private void setVisibleOnly(@NotNull VirtualFile root) { - myFilterModel.setFilter(new VcsLogFileFilter(null, VcsLogFilterObject.fromRoot(root))); + myFilterModel.setFilter(new FilterPair<>(null, VcsLogFilterObject.fromRoot(root))); } @NotNull @@ -302,7 +298,7 @@ class StructureFilterPopupComponent extends FilterPopupComponent filter = myFilterModel.getFilter(); Collection files; - if (filter == null || filter.getStructureFilter() == null) { + if (getStructureFilter(filter) == null) { files = Collections.emptySet(); } else { // for now, ignoring non-existing paths - files = ContainerUtil.mapNotNull(filter.getStructureFilter().getFiles(), FilePath::getVirtualFile); + files = ContainerUtil.mapNotNull(getStructureFilter(filter).getFiles(), FilePath::getVirtualFile); } VcsStructureChooser chooser = new VcsStructureChooser(project, "Select Files or Folders to Filter by", files, new ArrayList<>(dataPack.getLogProviders().keySet())); if (chooser.showAndGet()) { VcsLogStructureFilter structureFilter = VcsLogFilterObject.fromVirtualFiles(chooser.getSelectedFiles()); - myFilterModel.setFilter(new VcsLogFileFilter(structureFilter, null)); + myFilterModel.setFilter(new FilterPair<>(structureFilter, null)); myUiProperties.addRecentlyFilteredGroup(myName, VcsLogClassicFilterUi.FileFilterModel.getFilterValues(structureFilter)); } } @@ -388,12 +384,12 @@ class StructureFilterPopupComponent extends FilterPopupComponent(myFilter, null)); } @Override diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/UserFilterPopupComponent.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/UserFilterPopupComponent.java index 71d2f2947b2c..92218dcbea9d 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/UserFilterPopupComponent.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/UserFilterPopupComponent.java @@ -1,18 +1,4 @@ -/* - * 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.vcs.log.ui.filter; import com.intellij.ide.DataManager; @@ -25,8 +11,8 @@ import com.intellij.util.ui.JBDimension; import com.intellij.vcs.log.VcsLogUserFilter; import com.intellij.vcs.log.data.VcsLogData; import com.intellij.vcs.log.impl.MainVcsLogUiProperties; -import com.intellij.vcs.log.visible.filters.VcsLogUserFilterImpl; import com.intellij.vcs.log.util.VcsUserUtil; +import com.intellij.vcs.log.visible.filters.VcsLogUserFilterImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -38,13 +24,14 @@ import java.util.TreeSet; /** * Show a popup to select a user or enter the user name. */ -public class UserFilterPopupComponent extends MultipleValueFilterPopupComponent { +public class UserFilterPopupComponent + extends MultipleValueFilterPopupComponent> { public static final String USER_FILER_NAME = "User"; @NotNull private final VcsLogData myLogData; UserFilterPopupComponent(@NotNull MainVcsLogUiProperties uiProperties, @NotNull VcsLogData logData, - @NotNull FilterModel filterModel) { + @NotNull FilterModel.SingleFilterModel filterModel) { super(USER_FILER_NAME, uiProperties, filterModel); myLogData = logData; } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java index 015af062a4ab..fd32104ad0f8 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java @@ -25,7 +25,7 @@ import com.intellij.vcs.log.impl.MainVcsLogUiProperties; import com.intellij.vcs.log.ui.VcsLogActionPlaces; import com.intellij.vcs.log.ui.VcsLogUiImpl; import com.intellij.vcs.log.util.VcsLogUtil; -import com.intellij.vcs.log.visible.filters.VcsLogFileFilter; +import com.intellij.vcs.log.visible.filters.FilterPair; import com.intellij.vcs.log.visible.filters.VcsLogFilterObject; import com.intellij.vcs.log.visible.filters.VcsLogUserFilterImpl; import com.intellij.vcsUtil.VcsUtil; @@ -52,7 +52,7 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi { @NotNull private VcsLogDataPack myDataPack; @NotNull private final BranchFilterModel myBranchFilterModel; - @NotNull private final FilterModel myUserFilterModel; + @NotNull private final FilterModel.SingleFilterModel myUserFilterModel; @NotNull private final FilterModel myDateFilterModel; @NotNull private final FileFilterModel myStructureFilterModel; @NotNull private final TextFilterModel myTextFilterModel; @@ -83,8 +83,8 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi { for (FilterModel model : models) { model.addSetFilterListener(() -> { myUi.applyFiltersAndUpdateUi(getFilters()); - myBranchFilterModel - .onStructureFilterChanged(new HashSet<>(myLogData.getRoots()), myStructureFilterModel.getFilter()); + myBranchFilterModel.onStructureFilterChanged(new HashSet<>(myLogData.getRoots()), myStructureFilterModel.getRootFilter(), + myStructureFilterModel.getStructureFilter()); }); } } @@ -116,8 +116,8 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi { @Override public VcsLogFilterCollection getFilters() { ApplicationManager.getApplication().assertIsDispatchThread(); - return VcsLogFilterObject.collection(myBranchFilterModel.getFilter(), myUserFilterModel.getFilter(), myTextFilterModel.getHashFilters(), - myDateFilterModel.getFilter(), myTextFilterModel.getTextFilter(), + return VcsLogFilterObject.collection(myBranchFilterModel.getFilter(), myUserFilterModel.getFilter(), myTextFilterModel.getFilter2(), + myDateFilterModel.getFilter(), myTextFilterModel.getFilter1(), myStructureFilterModel.getStructureFilter(), myStructureFilterModel.getRootFilter()); } @@ -139,7 +139,7 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi { myBranchFilterModel.setFilter((VcsLogBranchFilter)filter); } else if (filter instanceof VcsLogStructureFilter) { - myStructureFilterModel.setFilter(new VcsLogFileFilter((VcsLogStructureFilter)filter, null)); + myStructureFilterModel.setStructureFilter((VcsLogStructureFilter)filter); } JComponent toolbar = myUi.getToolbar(); @@ -166,7 +166,7 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi { } } - public static class BranchFilterModel extends FilterModel { + public static class BranchFilterModel extends FilterModel.SingleFilterModel { @Nullable private Collection myVisibleRoots; @@ -175,12 +175,14 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi { super(VcsLogFilterCollection.BRANCH_FILTER, provider, properties, filters); } - public void onStructureFilterChanged(@NotNull Set roots, @Nullable VcsLogFileFilter filter) { - if (filter == null) { + public void onStructureFilterChanged(@NotNull Set roots, + @Nullable VcsLogRootFilter rootFilter, + @Nullable VcsLogStructureFilter structureFilter) { + if (rootFilter == null && structureFilter == null) { myVisibleRoots = null; } else { - myVisibleRoots = VcsLogUtil.getAllVisibleRoots(roots, filter.getRootFilter(), filter.getStructureFilter()); + myVisibleRoots = VcsLogUtil.getAllVisibleRoots(roots, rootFilter, structureFilter); } } @@ -203,12 +205,12 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi { } } - private static class TextFilterModel extends FilterModel { + private static class TextFilterModel extends FilterModel.PairFilterModel { @Nullable private String myText; TextFilterModel(@NotNull NotNullComputable dataPackProvider, @NotNull MainVcsLogUiProperties properties, @Nullable VcsLogFilterCollection filters) { - super(VcsLogFilterCollection.TEXT_FILTER, dataPackProvider, properties, filters); + super(VcsLogFilterCollection.TEXT_FILTER, VcsLogFilterCollection.HASH_FILTER, dataPackProvider, properties, filters); } @NotNull @@ -216,8 +218,8 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi { if (myText != null) { return myText; } - else if (getFilter() != null) { - return getFilter().getText(); + else if (getFilter1() != null) { + return getFilter1().getText(); } else { return ""; @@ -230,54 +232,59 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi { boolean hasUnsavedChanges() { if (myText == null) return false; - return getFilter() == null || !myText.equals(getFilter().getText()); + return getFilter1() == null || !myText.equals(getFilter1().getText()); } @Override - void setFilter(@Nullable VcsLogTextFilter filter) { + void setFilter(@Nullable FilterPair filter) { super.setFilter(filter); myText = null; } @NotNull @Override - protected VcsLogTextFilter createFilter(@NotNull List values) { - return VcsLogFilterObject.fromPattern(ObjectUtils.assertNotNull(ContainerUtil.getFirstItem(values)), - myUiProperties.get(MainVcsLogUiProperties.TEXT_FILTER_REGEX), - myUiProperties.get(MainVcsLogUiProperties.TEXT_FILTER_MATCH_CASE)); + protected List getFilter1Values(@NotNull VcsLogTextFilter filter) { + return Collections.singletonList(filter.getText()); } @NotNull @Override - protected List getFilterValues(@NotNull VcsLogTextFilter filter) { - return Collections.singletonList(filter.getText()); + protected List getFilter2Values(@NotNull VcsLogHashFilter filter) { + return ContainerUtil.newArrayList(filter.getHashes()); } @Nullable - VcsLogTextFilter getTextFilter() { - VcsLogTextFilter filter = getFilter(); - if (filter == null) return null; - String text = filter.getText().trim(); - if (StringUtil.isEmptyOrSpaces(text)) return null; + @Override + protected VcsLogTextFilter createFilter1(@NotNull List values) { + return createTextFilter(ObjectUtils.assertNotNull(ContainerUtil.getFirstItem(values))); + } - return VcsLogFilterObject.fromPattern(text, myUiProperties.get(MainVcsLogUiProperties.TEXT_FILTER_REGEX), + @Nullable + @Override + protected VcsLogHashFilter createFilter2(@NotNull List values) { + return VcsLogFilterObject.fromHashes(values); + } + + @NotNull + private VcsLogTextFilter createTextFilter(@NotNull String text) { + return VcsLogFilterObject.fromPattern(text, + myUiProperties.get(MainVcsLogUiProperties.TEXT_FILTER_REGEX), myUiProperties.get(MainVcsLogUiProperties.TEXT_FILTER_MATCH_CASE)); } - @Nullable - VcsLogHashFilter getHashFilters() { - VcsLogTextFilter filter = getFilter(); - if (filter == null) return null; - String text = filter.getText().trim(); - if (StringUtil.isEmptyOrSpaces(text)) return null; - - return VcsLogFilterObject.fromHash(text); + public void setFilterText(@NotNull String text) { + if (StringUtil.isEmptyOrSpaces(text)) { + setFilter(null); + } + else { + VcsLogTextFilter textFilter = createTextFilter(text); + VcsLogHashFilter hashFilter = VcsLogFilterObject.fromHash(text); + setFilter(new FilterPair<>(textFilter, hashFilter)); + } } } - static class FileFilterModel extends FilterModel { - @NotNull private static final String ROOTS = "roots"; - @NotNull private static final String STRUCTURE = "structure"; + static class FileFilterModel extends FilterModel.PairFilterModel { @NotNull private static final String DIR = "dir:"; @NotNull private static final String FILE = "file:"; @NotNull private final Set myRoots; @@ -286,31 +293,20 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi { @NotNull Set roots, @NotNull MainVcsLogUiProperties uiProperties, @Nullable VcsLogFilterCollection filters) { - super(VcsLogFileFilter.FILE_FILTER, dataPackGetter, uiProperties, filters); + super(VcsLogFilterCollection.STRUCTURE_FILTER, VcsLogFilterCollection.ROOT_FILTER, dataPackGetter, uiProperties, filters); myRoots = roots; } - @Nullable @Override - protected VcsLogFileFilter getFilterFromCollection(@NotNull VcsLogFilterCollection filters) { - VcsLogRootFilter rootFilter = filters.get(VcsLogFilterCollection.ROOT_FILTER); - VcsLogStructureFilter structureFilter = filters.get(VcsLogFilterCollection.STRUCTURE_FILTER); - if (rootFilter == null && structureFilter == null) return null; - return new VcsLogFileFilter(structureFilter, rootFilter); + @NotNull + protected List getFilter1Values(@NotNull VcsLogStructureFilter filter) { + return getFilterValues(filter); } @Override - protected void saveFilter(@Nullable VcsLogFileFilter filter) { - if (filter == null) { - myUiProperties.saveFilterValues(ROOTS, null); - myUiProperties.saveFilterValues(STRUCTURE, null); - } - else if (filter.getStructureFilter() != null) { - myUiProperties.saveFilterValues(STRUCTURE, getFilterValues(filter.getStructureFilter())); - } - else if (filter.getRootFilter() != null) { - myUiProperties.saveFilterValues(ROOTS, getFilterValues(filter.getRootFilter())); - } + @NotNull + protected List getFilter2Values(@NotNull VcsLogRootFilter filter) { + return ContainerUtil.map(filter.getRoots(), VirtualFile::getPath); } @NotNull @@ -318,40 +314,15 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi { return ContainerUtil.map(filter.getFiles(), path -> (path.isDirectory() ? DIR : FILE) + path.getPath()); } - @NotNull - private static List getFilterValues(@NotNull VcsLogRootFilter filter) { - return ContainerUtil.map(filter.getRoots(), VirtualFile::getPath); - } - - @NotNull - static VcsLogStructureFilter createStructureFilter(@NotNull List values) { - return VcsLogFilterObject.fromPaths(ContainerUtil.map(values, path -> { - if (path.startsWith(DIR)) { - return VcsUtil.getFilePath(path.substring(DIR.length()), true); - } - else if (path.startsWith(FILE)) { - return VcsUtil.getFilePath(path.substring(FILE.length()), false); - } - return VcsUtil.getFilePath(path); - })); - } - - @Nullable @Override - protected VcsLogFileFilter getLastFilter() { - List values = myUiProperties.getFilterValues(STRUCTURE); - if (values != null) { - return new VcsLogFileFilter(createStructureFilter(values), null); - } - values = myUiProperties.getFilterValues(ROOTS); - if (values != null) { - return new VcsLogFileFilter(null, createRootsFilter(values)); - } - return null; + @NotNull + protected VcsLogStructureFilter createFilter1(@NotNull List values) { + return createStructureFilter(values); } + @Override @Nullable - private VcsLogRootFilter createRootsFilter(@NotNull List values) { + protected VcsLogRootFilter createFilter2(@NotNull List values) { List selectedRoots = ContainerUtil.newArrayList(); for (String path : values) { VirtualFile root = LocalFileSystem.getInstance().findFileByPath(path); @@ -371,34 +342,35 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi { return VcsLogFilterObject.fromRoots(selectedRoots); } - @NotNull - @Override - protected VcsLogFileFilter createFilter(@NotNull List values) { - throw new UnsupportedOperationException("Can not create file filter from list of strings"); - } - - @NotNull - @Override - protected List getFilterValues(@NotNull VcsLogFileFilter filter) { - throw new UnsupportedOperationException("Can not save file filter to a list of strings"); + @Nullable + protected VcsLogRootFilter getRootFilter() { + return getFilter2(); } @Nullable - VcsLogRootFilter getRootFilter() { - VcsLogFileFilter filter = getFilter(); - if (filter == null) return null; - return filter.getRootFilter(); + protected VcsLogStructureFilter getStructureFilter() { + return getFilter1(); } - @Nullable - VcsLogStructureFilter getStructureFilter() { - VcsLogFileFilter filter = getFilter(); - if (filter == null) return null; - return filter.getStructureFilter(); + protected void setStructureFilter(@NotNull VcsLogStructureFilter filter) { + setFilter(new FilterPair<>(filter, null)); + } + + @NotNull + static VcsLogStructureFilter createStructureFilter(@NotNull List values) { + return VcsLogFilterObject.fromPaths(ContainerUtil.map(values, path -> { + if (path.startsWith(DIR)) { + return VcsUtil.getFilePath(path.substring(DIR.length()), true); + } + else if (path.startsWith(FILE)) { + return VcsUtil.getFilePath(path.substring(FILE.length()), false); + } + return VcsUtil.getFilePath(path); + })); } } - private static class DateFilterModel extends FilterModel { + private static class DateFilterModel extends FilterModel.SingleFilterModel { DateFilterModel(@NotNull NotNullComputable dataPackGetter, @NotNull MainVcsLogUiProperties uiProperties, @Nullable VcsLogFilterCollection filters) { super(VcsLogFilterCollection.DATE_FILTER, dataPackGetter, uiProperties, filters); @@ -433,7 +405,7 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi { } } - private class UserFilterModel extends FilterModel { + private class UserFilterModel extends FilterModel.SingleFilterModel { UserFilterModel(@NotNull NotNullComputable dataPackGetter, @NotNull MainVcsLogUiProperties uiProperties, @Nullable VcsLogFilterCollection filters) { super(VcsLogFilterCollection.USER_FILTER, dataPackGetter, uiProperties, filters); @@ -478,9 +450,7 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi { } protected void applyFilter() { - boolean isRegexpAllowed = myTextFilterModel.myUiProperties.get(MainVcsLogUiProperties.TEXT_FILTER_REGEX); - boolean isMatchCase = myTextFilterModel.myUiProperties.get(MainVcsLogUiProperties.TEXT_FILTER_MATCH_CASE); - myTextFilterModel.setFilter(VcsLogFilterObject.fromPattern(getText(), isRegexpAllowed, isMatchCase)); + myTextFilterModel.setFilterText(getText()); addCurrentTextToHistory(); } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/visible/filters/FilterPair.kt b/platform/vcs-log/impl/src/com/intellij/vcs/log/visible/filters/FilterPair.kt new file mode 100644 index 000000000000..2e74e1d05795 --- /dev/null +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/visible/filters/FilterPair.kt @@ -0,0 +1,6 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.vcs.log.visible.filters + +import com.intellij.vcs.log.VcsLogFilter + +data class FilterPair(val filter1: F1?, val filter2: F2?) \ No newline at end of file diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/visible/filters/VcsLogFileFilter.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/visible/filters/VcsLogFileFilter.java deleted file mode 100644 index 7767297781b9..000000000000 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/visible/filters/VcsLogFileFilter.java +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -package com.intellij.vcs.log.visible.filters; - -import com.intellij.vcs.log.VcsLogFilter; -import com.intellij.vcs.log.VcsLogFilterCollection; -import com.intellij.vcs.log.VcsLogRootFilter; -import com.intellij.vcs.log.VcsLogStructureFilter; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class VcsLogFileFilter implements VcsLogFilter { - public static final VcsLogFilterCollection.FilterKey FILE_FILTER = VcsLogFilterCollection.FilterKey.create("file"); - @Nullable private final VcsLogStructureFilter myStructureFilter; - @Nullable private final VcsLogRootFilter myRootFilter; - - public VcsLogFileFilter(@Nullable VcsLogStructureFilter structureFilter, @Nullable VcsLogRootFilter rootFilter) { - myStructureFilter = structureFilter; - myRootFilter = rootFilter; - } - - @Nullable - public VcsLogStructureFilter getStructureFilter() { - return myStructureFilter; - } - - @Nullable - public VcsLogRootFilter getRootFilter() { - return myRootFilter; - } - - @NotNull - @Override - public VcsLogFilterCollection.FilterKey getKey() { - return FILE_FILTER; - } - - @NotNull - @Override - public String getPresentation() { - StringBuilder result = new StringBuilder(); - if (myRootFilter != null) { - result.append(myRootFilter.getPresentation()); - } - if (myStructureFilter != null) { - if (result.length() > 0) { - result.append(" "); - } - result.append(myStructureFilter.getPresentation()); - } - return result.toString(); - } -}