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.
18 * Created by IntelliJ IDEA.
23 package com
.intellij
.openapi
.vcs
.changes
.committed
;
25 import com
.intellij
.openapi
.Disposable
;
26 import com
.intellij
.openapi
.actionSystem
.*;
27 import com
.intellij
.openapi
.diagnostic
.Logger
;
28 import com
.intellij
.openapi
.progress
.ProgressManager
;
29 import com
.intellij
.openapi
.project
.Project
;
30 import com
.intellij
.openapi
.ui
.Messages
;
31 import com
.intellij
.openapi
.util
.Ref
;
32 import com
.intellij
.openapi
.util
.text
.StringUtil
;
33 import com
.intellij
.openapi
.vcs
.*;
34 import com
.intellij
.openapi
.vcs
.versionBrowser
.ChangeBrowserSettings
;
35 import com
.intellij
.openapi
.vcs
.versionBrowser
.CommittedChangeList
;
36 import com
.intellij
.openapi
.vfs
.VirtualFile
;
37 import com
.intellij
.ui
.FilterComponent
;
38 import com
.intellij
.util
.Consumer
;
39 import org
.jetbrains
.annotations
.NotNull
;
40 import org
.jetbrains
.annotations
.Nullable
;
44 import java
.util
.ArrayList
;
45 import java
.util
.Collections
;
46 import java
.util
.List
;
48 public class CommittedChangesPanel
extends JPanel
implements TypeSafeDataProvider
, Disposable
{
49 private static final Logger LOG
= Logger
.getInstance("#com.intellij.openapi.vcs.changes.committed.CommittedChangesPanel");
51 private final CommittedChangesTreeBrowser myBrowser
;
52 private final Project myProject
;
53 private CommittedChangesProvider myProvider
;
54 private ChangeBrowserSettings mySettings
;
55 private final RepositoryLocation myLocation
;
56 private int myMaxCount
= 0;
57 private final FilterComponent myFilterComponent
= new MyFilterComponent();
58 private List
<CommittedChangeList
> myChangesFromProvider
;
59 private final JLabel myErrorLabel
= new JLabel();
60 private final List
<Runnable
> myShouldBeCalledOnDispose
;
62 public CommittedChangesPanel(Project project
, final CommittedChangesProvider provider
, final ChangeBrowserSettings settings
,
63 @Nullable final RepositoryLocation location
, @Nullable ActionGroup extraActions
) {
64 super(new BorderLayout());
65 mySettings
= settings
;
67 myProvider
= provider
;
68 myLocation
= location
;
69 myShouldBeCalledOnDispose
= new ArrayList
<Runnable
>();
70 myBrowser
= new CommittedChangesTreeBrowser(project
, new ArrayList
<CommittedChangeList
>());
71 add(myBrowser
, BorderLayout
.CENTER
);
73 myErrorLabel
.setForeground(Color
.red
);
74 add(myErrorLabel
, BorderLayout
.SOUTH
);
76 final VcsCommittedViewAuxiliary auxiliary
= provider
.createActions(myBrowser
, location
);
78 JPanel toolbarPanel
= new JPanel(new BorderLayout());
79 ActionGroup group
= (ActionGroup
) ActionManager
.getInstance().getAction("CommittedChangesToolbar");
81 ActionToolbar toolBar
= myBrowser
.createGroupFilterToolbar(project
, group
, extraActions
,
82 auxiliary
!= null ? auxiliary
.getToolbarActions() : Collections
.<AnAction
>emptyList());
83 toolbarPanel
.add(toolBar
.getComponent(), BorderLayout
.WEST
);
85 toolbarPanel
.add(myFilterComponent
, BorderLayout
.EAST
);
86 myBrowser
.addToolBar(toolbarPanel
);
88 if (auxiliary
!= null) {
89 myShouldBeCalledOnDispose
.add(auxiliary
.getCalledOnViewDispose());
90 myBrowser
.setTableContextMenu(group
, (auxiliary
.getPopupActions() == null) ? Collections
.<AnAction
>emptyList() : auxiliary
.getPopupActions());
92 myBrowser
.setTableContextMenu(group
, Collections
.<AnAction
>emptyList());
95 final AnAction anAction
= ActionManager
.getInstance().getAction("CommittedChanges.Refresh");
96 anAction
.registerCustomShortcutSet(CommonShortcuts
.getRerun(), this);
99 public RepositoryLocation
getRepositoryLocation() {
103 public void setMaxCount(final int maxCount
) {
104 myMaxCount
= maxCount
;
107 public void setProvider(final CommittedChangesProvider provider
) {
108 if (myProvider
!= provider
) {
109 myProvider
= provider
;
110 mySettings
= provider
.createDefaultSettings();
114 public void refreshChanges(final boolean cacheOnly
) {
115 if (myLocation
!= null) {
116 refreshChangesFromLocation();
119 refreshChangesFromCache(cacheOnly
);
123 private void refreshChangesFromLocation() {
124 final Ref
<VcsException
> refEx
= new Ref
<VcsException
>();
125 final Ref
<List
<CommittedChangeList
>> changes
= new Ref
<List
<CommittedChangeList
>>();
126 boolean completed
= ProgressManager
.getInstance().runProcessWithProgressSynchronously(new Runnable() {
129 changes
.set(myProvider
.getCommittedChanges(mySettings
, myLocation
, myMaxCount
));
131 catch (VcsException ex
) {
135 }, "Loading changes", true, myProject
);
136 if (!refEx
.isNull()) {
137 LOG
.info(refEx
.get());
138 Messages
.showErrorDialog(myProject
, "Error refreshing view: " + StringUtil
.join(refEx
.get().getMessages(), "\n"), "Committed Changes");
140 else if (completed
) {
141 myChangesFromProvider
= changes
.get();
142 updateFilteredModel(false);
146 private void refreshChangesFromCache(final boolean cacheOnly
) {
147 final CommittedChangesCache cache
= CommittedChangesCache
.getInstance(myProject
);
148 if (!cache
.hasCachesForAnyRoot()) {
150 myBrowser
.setEmptyText(VcsBundle
.message("committed.changes.not.loaded.message"));
153 if (!CacheSettingsDialog
.showSettingsDialog(myProject
)) return;
155 cache
.getProjectChangesAsync(mySettings
, myMaxCount
, cacheOnly
,
156 new Consumer
<List
<CommittedChangeList
>>() {
157 public void consume(final List
<CommittedChangeList
> committedChangeLists
) {
158 myChangesFromProvider
= committedChangeLists
;
159 updateFilteredModel(false);
162 new Consumer
<List
<VcsException
>>() {
163 public void consume(final List
<VcsException
> vcsExceptions
) {
164 AbstractVcsHelper
.getInstance(myProject
).showErrors(vcsExceptions
, "Error refreshing VCS history");
169 private void updateFilteredModel(final boolean keepFilter
) {
170 if (myChangesFromProvider
== null) {
173 myBrowser
.setEmptyText(VcsBundle
.message("committed.changes.empty.message"));
174 if (StringUtil
.isEmpty(myFilterComponent
.getFilter())) {
175 myBrowser
.setItems(myChangesFromProvider
, keepFilter
, CommittedChangesBrowserUseCase
.COMMITTED
);
178 final String
[] strings
= myFilterComponent
.getFilter().split(" ");
179 for(int i
=0; i
<strings
.length
; i
++) {
180 strings
[i
] = strings
[i
].toLowerCase();
182 List
<CommittedChangeList
> filteredChanges
= new ArrayList
<CommittedChangeList
>();
183 for(CommittedChangeList changeList
: myChangesFromProvider
) {
184 if (changeListMatches(changeList
, strings
)) {
185 filteredChanges
.add(changeList
);
188 myBrowser
.setItems(filteredChanges
, keepFilter
, CommittedChangesBrowserUseCase
.COMMITTED
);
192 private static boolean changeListMatches(@NotNull final CommittedChangeList changeList
, final String
[] filterWords
) {
193 for(String word
: filterWords
) {
194 final String comment
= changeList
.getComment();
195 final String committer
= changeList
.getCommitterName();
196 if ((comment
!= null && comment
.toLowerCase().indexOf(word
) >= 0) ||
197 (committer
!= null && committer
.toLowerCase().indexOf(word
) >= 0) ||
198 Long
.toString(changeList
.getNumber()).indexOf(word
) >= 0) {
205 public void setChangesFilter() {
206 CommittedChangesFilterDialog filterDialog
= new CommittedChangesFilterDialog(myProject
, myProvider
.createFilterUI(true), mySettings
);
208 if (filterDialog
.isOK()) {
209 mySettings
= filterDialog
.getSettings();
210 refreshChanges(false);
214 public void calcData(DataKey key
, DataSink sink
) {
215 if (key
.equals(VcsDataKeys
.CHANGES
) || key
.equals(VcsDataKeys
.CHANGE_LISTS
)) {
216 myBrowser
.calcData(key
, sink
);
220 public void dispose() {
222 for (Runnable runnable
: myShouldBeCalledOnDispose
) {
227 public void setErrorText(String text
) {
228 myErrorLabel
.setText(text
);
231 private class MyFilterComponent
extends FilterComponent
{
232 public MyFilterComponent() {
233 super("COMMITTED_CHANGES_FILTER_HISTORY", 20);
236 public void filter() {
237 updateFilteredModel(true);
241 public void passCachedListsToListener(final VcsConfigurationChangeListener
.DetailedNotification notification
,
242 final Project project
, final VirtualFile root
) {
243 if ((myChangesFromProvider
!= null) && (! myChangesFromProvider
.isEmpty())) {
244 notification
.execute(project
, root
, myChangesFromProvider
);