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.ui;
25 import com.intellij.openapi.actionSystem.*;
26 import com.intellij.openapi.application.ApplicationManager;
27 import com.intellij.openapi.application.ModalityState;
28 import com.intellij.openapi.project.Project;
29 import com.intellij.openapi.ui.DialogWrapper;
30 import com.intellij.openapi.util.Comparing;
31 import com.intellij.openapi.util.IconLoader;
32 import com.intellij.openapi.vcs.AbstractVcs;
33 import com.intellij.openapi.vcs.VcsBundle;
34 import com.intellij.openapi.vcs.changes.*;
35 import com.intellij.openapi.vcs.changes.actions.MoveChangesToAnotherListAction;
36 import com.intellij.openapi.vcs.changes.actions.RollbackDialogAction;
37 import com.intellij.ui.ColoredListCellRenderer;
38 import com.intellij.ui.SimpleTextAttributes;
39 import com.intellij.util.EventDispatcher;
40 import org.jetbrains.annotations.NotNull;
41 import org.jetbrains.annotations.Nullable;
45 import java.awt.event.ItemEvent;
46 import java.awt.event.ItemListener;
48 import java.util.List;
50 public class MultipleChangeListBrowser extends ChangesBrowser {
51 private final ChangeListChooser myChangeListChooser;
52 private final ChangeListListener myChangeListListener = new MyChangeListListener();
53 private final boolean myShowingAllChangeLists;
54 private final EventDispatcher<SelectedListChangeListener> myDispatcher = EventDispatcher.create(SelectedListChangeListener.class);
55 private Collection<Change> myAllChanges;
56 private Map<Change, LocalChangeList> myChangeListsMap;
58 private final ChangesBrowserExtender myExtender;
59 private final Runnable myRebuildListListener;
61 public MultipleChangeListBrowser(final Project project, final List<? extends ChangeList> changeLists, final List<Change> changes,
62 final ChangeList initialListSelection,
63 final boolean capableOfExcludingChanges,
64 final boolean highlightProblems, final Runnable rebuildListListener, @Nullable final Runnable inclusionListener) {
65 super(project, changeLists, changes, initialListSelection, capableOfExcludingChanges, highlightProblems, inclusionListener, MyUseCase.LOCAL_CHANGES);
66 myRebuildListListener = rebuildListListener;
68 myChangeListChooser = new ChangeListChooser(changeLists);
69 myHeaderPanel.add(myChangeListChooser, BorderLayout.EAST);
70 myShowingAllChangeLists = Comparing.haveEqualElements((List<LocalChangeList>) changeLists, ChangeListManager.getInstance(project).getChangeLists());
71 ChangeListManager.getInstance(myProject).addChangeListListener(myChangeListListener);
73 myExtender = new Extender(project, this);
77 protected void setInitialSelection(final List<? extends ChangeList> changeLists, final List<Change> changes, final ChangeList initialListSelection) {
78 myAllChanges = new ArrayList<Change>();
79 mySelectedChangeList = initialListSelection;
81 for (ChangeList list : changeLists) {
82 if (list instanceof LocalChangeList) {
83 myAllChanges.addAll(list.getChanges());
84 if (initialListSelection == null) {
85 for(Change c: list.getChanges()) {
86 if (changes.contains(c)) {
87 mySelectedChangeList = list;
95 if (mySelectedChangeList == null) {
96 for(ChangeList list: changeLists) {
97 if (list instanceof LocalChangeList && ((LocalChangeList) list).isDefault()) {
98 mySelectedChangeList = list;
102 if (mySelectedChangeList == null && !changeLists.isEmpty()) {
103 mySelectedChangeList = changeLists.get(0);
109 public void dispose() {
110 ChangeListManager.getInstance(myProject).removeChangeListListener(myChangeListListener);
113 public Collection<Change> getAllChanges() {
117 public ChangesBrowserExtender getExtender() {
121 public void addSelectedListChangeListener(SelectedListChangeListener listener) {
122 myDispatcher.addListener(listener);
125 public void removeSelectedListChangeListener(SelectedListChangeListener listener) {
126 myDispatcher.removeListener(listener);
129 private void setSelectedList(final ChangeList list) {
130 mySelectedChangeList = list;
132 myDispatcher.getMulticaster().selectedListChanged();
135 private boolean myInRebuildList;
138 public void rebuildList() {
139 if (myInRebuildList) return;
141 myInRebuildList = true;
142 if (myChangesToDisplay == null) {
143 // changes set not fixed === local changes
144 final ChangeListManager manager = ChangeListManager.getInstance(myProject);
145 myChangeListsMap = new HashMap<Change, LocalChangeList>();
146 final List<LocalChangeList> lists = manager.getChangeListsCopy();
147 Collection<Change> allChanges = new ArrayList<Change>();
148 for (LocalChangeList list : lists) {
149 final Collection<Change> changes = list.getChanges();
150 allChanges.addAll(changes);
151 for (Change change : changes) {
152 myChangeListsMap.put(change, list);
155 myAllChanges = allChanges;
156 // refresh selected list also
157 updateListsInChooser();
161 if (myRebuildListListener != null) {
162 myRebuildListListener.run();
165 myInRebuildList = false;
170 public List<Change> getCurrentDisplayedChanges() {
171 if (myChangesToDisplay == null) {
172 return sortChanges(filterBySelectedChangeList(myAllChanges));
174 return super.getCurrentDisplayedChanges();
178 public List<Change> getCurrentIncludedChanges() {
179 return filterBySelectedChangeList(myViewer.getIncludedChanges());
182 private List<Change> filterBySelectedChangeList(final Collection<Change> changes) {
183 List<Change> filtered = new ArrayList<Change>();
184 for (Change change : changes) {
185 if (Comparing.equal(getList(change), mySelectedChangeList)) {
186 filtered.add(change);
192 private ChangeList getList(final Change change) {
193 return myChangeListsMap.get(change);
197 protected void buildToolBar(final DefaultActionGroup toolBarGroup) {
198 super.buildToolBar(toolBarGroup);
200 final MoveChangesToAnotherListAction moveAction = new MoveChangesToAnotherListAction() {
201 public void actionPerformed(AnActionEvent e) {
202 super.actionPerformed(e);
207 moveAction.registerCustomShortcutSet(CommonShortcuts.getMove(), myViewer);
208 toolBarGroup.add(moveAction);
212 protected List<AnAction> createDiffActions(final Change change) {
213 List<AnAction> actions = super.createDiffActions(change);
214 actions.add(new MoveAction(change));
218 private class ChangeListChooser extends JPanel {
219 private final JComboBox myChooser;
220 private final static int MAX_LEN = 35;
222 public ChangeListChooser(List<? extends ChangeList> lists) {
223 super(new BorderLayout());
224 myChooser = new JComboBox() {
225 public Dimension getMinimumSize() {
226 return new Dimension(0, 0);
229 myChooser.setRenderer(new ColoredListCellRenderer() {
230 protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) {
231 final LocalChangeList l = ((LocalChangeList)value);
233 String name = l.getName().trim();
234 if (name.length() > MAX_LEN) {
235 name = name.substring(0, MAX_LEN - 3) + "...";
237 append(name, l.isDefault() ? SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES : SimpleTextAttributes.REGULAR_ATTRIBUTES);
242 myChooser.addItemListener(new ItemListener() {
243 public void itemStateChanged(ItemEvent e) {
244 if (e.getStateChange() == ItemEvent.SELECTED) {
245 final LocalChangeList changeList = (LocalChangeList)myChooser.getSelectedItem();
246 setSelectedList(changeList);
247 myChooser.setToolTipText(changeList == null ? "" : (changeList.getName()));
253 myChooser.setEditable(false);
254 add(myChooser, BorderLayout.CENTER);
256 JLabel label = new JLabel(VcsBundle.message("commit.dialog.changelist.label"));
257 label.setDisplayedMnemonic('l');
258 label.setLabelFor(myChooser);
259 add(label, BorderLayout.WEST);
262 public void updateLists(List<? extends ChangeList> lists) {
263 myChooser.setModel(new DefaultComboBoxModel(lists.toArray()));
264 myChooser.setEnabled(lists.size() > 1);
265 if (lists.contains(mySelectedChangeList)) {
266 myChooser.setSelectedItem(mySelectedChangeList);
268 if (myChooser.getItemCount() > 0) {
269 myChooser.setSelectedIndex(0);
272 mySelectedChangeList = (ChangeList) myChooser.getSelectedItem();
276 private class MyChangeListListener extends ChangeListAdapter {
277 public void changeListAdded(ChangeList list) {
278 updateListsInChooser();
282 private void updateListsInChooser() {
283 Runnable runnable = new Runnable() {
285 if (myChangeListChooser != null && myShowingAllChangeLists) {
286 myChangeListChooser.updateLists(ChangeListManager.getInstance(myProject).getChangeListsCopy());
290 if (SwingUtilities.isEventDispatchThread()) {
294 ApplicationManager.getApplication().invokeLater(runnable, ModalityState.stateForComponent(MultipleChangeListBrowser.this));
298 private class MoveAction extends MoveChangesToAnotherListAction {
299 private final Change myChange;
301 public MoveAction(final Change change) {
305 public void actionPerformed(AnActionEvent e) {
306 askAndMove(myProject, new Change[]{myChange}, null);
310 private static class Extender implements ChangesBrowserExtender {
311 private final Project myProject;
312 private final MultipleChangeListBrowser myBrowser;
314 private Extender(final Project project, final MultipleChangeListBrowser browser) {
319 public void addToolbarActions(final DialogWrapper dialogWrapper) {
320 final Icon icon = IconLoader.getIcon("/vcs/refresh.png");
321 if (myBrowser.myChangesToDisplay == null) {
322 myBrowser.addToolbarAction(new AnAction("Refresh Changes") {
324 public void actionPerformed(AnActionEvent e) {
325 myBrowser.rebuildList();
329 public void update(AnActionEvent e) {
330 e.getPresentation().setIcon(icon);
334 myBrowser.addToolbarAction(new RollbackDialogAction());
335 final EditSourceInCommitAction editSourceAction = new EditSourceInCommitAction(dialogWrapper);
336 editSourceAction.registerCustomShortcutSet(CommonShortcuts.getEditSource(), myBrowser);
337 myBrowser.addToolbarAction(editSourceAction);
339 myBrowser.addToolbarAction(ActionManager.getInstance().getAction("Vcs.CheckinProjectToolbar"));
341 final List<AnAction> actions = AdditionalLocalChangeActionsInstaller.calculateActions(myProject, myBrowser.getAllChanges());
342 if (actions != null) {
343 for (AnAction action : actions) {
344 myBrowser.addToolbarAction(action);
349 public void addSelectedListChangeListener(final SelectedListChangeListener listener) {
350 myBrowser.addSelectedListChangeListener(listener);
353 public List<AbstractVcs> getAffectedVcses() {
354 Set<AbstractVcs> result = new HashSet<AbstractVcs>();
355 for (Change change : myBrowser.myAllChanges) {
356 final AbstractVcs vcs = ChangesUtil.getVcsForChange(change, myBrowser.myProject);
361 return new ArrayList<AbstractVcs>(result);
364 public List<Change> getCurrentIncludedChanges() {
365 return myBrowser.getCurrentIncludedChanges();