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
.shelf
;
25 import com
.intellij
.ide
.DataManager
;
26 import com
.intellij
.ide
.DeleteProvider
;
27 import com
.intellij
.ide
.util
.treeView
.TreeState
;
28 import com
.intellij
.openapi
.actionSystem
.*;
29 import com
.intellij
.openapi
.application
.ApplicationManager
;
30 import com
.intellij
.openapi
.application
.ModalityState
;
31 import com
.intellij
.openapi
.components
.ProjectComponent
;
32 import com
.intellij
.openapi
.diff
.impl
.patch
.FilePatch
;
33 import com
.intellij
.openapi
.diff
.impl
.patch
.PatchSyntaxException
;
34 import com
.intellij
.openapi
.fileTypes
.FileTypeManager
;
35 import com
.intellij
.openapi
.fileTypes
.StdFileTypes
;
36 import com
.intellij
.openapi
.project
.Project
;
37 import com
.intellij
.openapi
.ui
.Messages
;
38 import com
.intellij
.openapi
.util
.Pair
;
39 import com
.intellij
.openapi
.vcs
.*;
40 import com
.intellij
.openapi
.vcs
.changes
.Change
;
41 import com
.intellij
.openapi
.vcs
.changes
.issueLinks
.IssueLinkRenderer
;
42 import com
.intellij
.openapi
.vcs
.changes
.issueLinks
.TreeLinkMouseListener
;
43 import com
.intellij
.openapi
.vcs
.changes
.patch
.RelativePathCalculator
;
44 import com
.intellij
.openapi
.vcs
.changes
.ui
.ChangesViewContentManager
;
45 import com
.intellij
.openapi
.wm
.ToolWindow
;
46 import com
.intellij
.openapi
.wm
.ToolWindowManager
;
47 import com
.intellij
.ui
.ColoredTreeCellRenderer
;
48 import com
.intellij
.ui
.PopupHandler
;
49 import com
.intellij
.ui
.SimpleTextAttributes
;
50 import com
.intellij
.ui
.TreeSpeedSearch
;
51 import com
.intellij
.ui
.content
.Content
;
52 import com
.intellij
.ui
.content
.ContentFactory
;
53 import com
.intellij
.ui
.treeStructure
.Tree
;
54 import com
.intellij
.util
.containers
.Convertor
;
55 import com
.intellij
.util
.messages
.MessageBus
;
56 import com
.intellij
.util
.ui
.tree
.TreeUtil
;
57 import org
.jetbrains
.annotations
.NonNls
;
58 import org
.jetbrains
.annotations
.NotNull
;
59 import org
.jetbrains
.annotations
.Nullable
;
62 import javax
.swing
.event
.ChangeEvent
;
63 import javax
.swing
.event
.ChangeListener
;
64 import javax
.swing
.tree
.DefaultMutableTreeNode
;
65 import javax
.swing
.tree
.DefaultTreeModel
;
66 import javax
.swing
.tree
.TreeModel
;
67 import javax
.swing
.tree
.TreePath
;
68 import java
.awt
.event
.MouseAdapter
;
69 import java
.awt
.event
.MouseEvent
;
71 import java
.io
.IOException
;
72 import java
.text
.SimpleDateFormat
;
75 public class ShelvedChangesViewManager
implements ProjectComponent
{
76 private final ChangesViewContentManager myContentManager
;
77 private final ShelveChangesManager myShelveChangesManager
;
78 private final Project myProject
;
79 private final Tree myTree
= new ShelfTree();
80 private Content myContent
= null;
81 private final ShelvedChangeDeleteProvider myDeleteProvider
= new ShelvedChangeDeleteProvider();
82 private boolean myUpdatePending
= false;
83 private Runnable myPostUpdateRunnable
= null;
85 public static DataKey
<ShelvedChangeList
[]> SHELVED_CHANGELIST_KEY
= DataKey
.create("ShelveChangesManager.ShelvedChangeListData");
86 public static DataKey
<ShelvedChangeList
[]> SHELVED_RECYCLED_CHANGELIST_KEY
= DataKey
.create("ShelveChangesManager.ShelvedRecycledChangeListData");
87 public static DataKey
<List
<ShelvedChange
>> SHELVED_CHANGE_KEY
= DataKey
.create("ShelveChangesManager.ShelvedChange");
88 public static DataKey
<List
<ShelvedBinaryFile
>> SHELVED_BINARY_FILE_KEY
= DataKey
.create("ShelveChangesManager.ShelvedBinaryFile");
89 private static final Object ROOT_NODE_VALUE
= new Object();
90 private DefaultMutableTreeNode myRoot
;
91 private final Map
<Pair
<String
, String
>, String
> myMoveRenameInfo
;
93 public static ShelvedChangesViewManager
getInstance(Project project
) {
94 return project
.getComponent(ShelvedChangesViewManager
.class);
97 public ShelvedChangesViewManager(Project project
, ChangesViewContentManager contentManager
, ShelveChangesManager shelveChangesManager
,
98 final MessageBus bus
) {
100 myContentManager
= contentManager
;
101 myShelveChangesManager
= shelveChangesManager
;
102 bus
.connect().subscribe(ShelveChangesManager
.SHELF_TOPIC
, new ChangeListener() {
103 public void stateChanged(ChangeEvent e
) {
104 myUpdatePending
= true;
105 ApplicationManager
.getApplication().invokeLater(new Runnable() {
107 updateChangesContent();
109 }, ModalityState
.NON_MODAL
);
112 myMoveRenameInfo
= new HashMap
<Pair
<String
, String
>, String
>();
114 myTree
.setRootVisible(false);
115 myTree
.setShowsRootHandles(true);
116 myTree
.setCellRenderer(new ShelfTreeCellRenderer(project
, myMoveRenameInfo
));
117 new TreeLinkMouseListener(new ShelfTreeCellRenderer(project
, myMoveRenameInfo
)).install(myTree
);
119 final AnAction showDiffAction
= ActionManager
.getInstance().getAction("ShelvedChanges.Diff");
120 showDiffAction
.registerCustomShortcutSet(CommonShortcuts
.getDiff(), myTree
);
122 PopupHandler
.installPopupHandler(myTree
, "ShelvedChangesPopupMenu", ActionPlaces
.UNKNOWN
);
124 myTree
.addMouseListener(new MouseAdapter() {
125 public void mouseClicked(final MouseEvent e
) {
126 if (e
.getClickCount() != 2) return;
128 DiffShelvedChangesAction
.showShelvedChangesDiff(DataManager
.getInstance().getDataContext(myTree
));
131 new TreeSpeedSearch(myTree
, new Convertor
<TreePath
, String
>() {
132 public String
convert(TreePath o
) {
133 final Object lc
= o
.getLastPathComponent();
134 final Object lastComponent
= lc
== null ?
null : ((DefaultMutableTreeNode
) lc
).getUserObject();
135 if (lastComponent
instanceof ShelvedChangeList
) {
136 return ((ShelvedChangeList
) lastComponent
).DESCRIPTION
;
137 } else if (lastComponent
instanceof ShelvedChange
) {
138 final ShelvedChange shelvedChange
= (ShelvedChange
)lastComponent
;
139 return shelvedChange
.getBeforeFileName() == null ? shelvedChange
.getAfterFileName() : shelvedChange
.getBeforeFileName();
140 } else if (lastComponent
instanceof ShelvedBinaryFile
) {
141 final ShelvedBinaryFile sbf
= (ShelvedBinaryFile
) lastComponent
;
142 final String value
= sbf
.BEFORE_PATH
== null ? sbf
.AFTER_PATH
: sbf
.BEFORE_PATH
;
143 int idx
= value
.lastIndexOf("/");
144 idx
= (idx
== -1) ? value
.lastIndexOf("\\") : idx
;
145 return idx
> 0 ? value
.substring(idx
+ 1) : value
;
152 public void projectOpened() {
153 updateChangesContent();
156 public void projectClosed() {
160 public String
getComponentName() {
161 return "ShelvedChangesViewManager";
164 public void initComponent() {
167 public void disposeComponent() {
170 private void updateChangesContent() {
171 myUpdatePending
= false;
172 final List
<ShelvedChangeList
> changeLists
= new ArrayList
<ShelvedChangeList
>(myShelveChangesManager
.getShelvedChangeLists());
173 changeLists
.addAll(myShelveChangesManager
.getRecycledShelvedChangeLists());
174 if (changeLists
.size() == 0) {
175 if (myContent
!= null) {
176 myContentManager
.removeContent(myContent
);
177 myContentManager
.selectContent("Local");
182 if (myContent
== null) {
183 myContent
= ContentFactory
.SERVICE
.getInstance().createContent(new JScrollPane(myTree
), VcsBundle
.message("shelf.tab"), false);
184 myContent
.setCloseable(false);
185 myContentManager
.addContent(myContent
);
187 TreeState state
= TreeState
.createOn(myTree
);
188 myTree
.setModel(buildChangesModel());
189 state
.applyTo(myTree
);
190 if (myPostUpdateRunnable
!= null) {
191 myPostUpdateRunnable
.run();
194 myPostUpdateRunnable
= null;
197 private TreeModel
buildChangesModel() {
198 myRoot
= new DefaultMutableTreeNode(ROOT_NODE_VALUE
); // not null for TreeState matching to work
199 DefaultTreeModel model
= new DefaultTreeModel(myRoot
);
200 final List
<ShelvedChangeList
> changeLists
= new ArrayList
<ShelvedChangeList
>(myShelveChangesManager
.getShelvedChangeLists());
201 if (myShelveChangesManager
.isShowRecycled()) {
202 changeLists
.addAll(myShelveChangesManager
.getRecycledShelvedChangeLists());
204 myMoveRenameInfo
.clear();
206 for(ShelvedChangeList changeList
: changeLists
) {
207 DefaultMutableTreeNode node
= new DefaultMutableTreeNode(changeList
);
208 model
.insertNodeInto(node
, myRoot
, myRoot
.getChildCount());
210 final List
<Object
> shelvedFilesNodes
= new ArrayList
<Object
>();
211 List
<ShelvedChange
> changes
= changeList
.getChanges();
212 for(ShelvedChange change
: changes
) {
213 putMovedMessage(change
.getBeforePath(), change
.getAfterPath());
214 shelvedFilesNodes
.add(change
);
216 List
<ShelvedBinaryFile
> binaryFiles
= changeList
.getBinaryFiles();
217 for(ShelvedBinaryFile file
: binaryFiles
) {
218 putMovedMessage(file
.BEFORE_PATH
, file
.AFTER_PATH
);
219 shelvedFilesNodes
.add(file
);
221 Collections
.sort(shelvedFilesNodes
, ShelvedFilePatchComparator
.getInstance());
222 for (int i
= 0; i
< shelvedFilesNodes
.size(); i
++) {
223 final Object filesNode
= shelvedFilesNodes
.get(i
);
224 final DefaultMutableTreeNode pathNode
= new DefaultMutableTreeNode(filesNode
);
225 model
.insertNodeInto(pathNode
, node
, i
);
231 private void putMovedMessage(final String beforeName
, final String afterName
) {
232 final String movedMessage
= RelativePathCalculator
.getMovedString(beforeName
, afterName
);
233 if (movedMessage
!= null) {
234 myMoveRenameInfo
.put(new Pair
<String
, String
>(beforeName
, afterName
), movedMessage
);
238 public void activateView(final ShelvedChangeList list
) {
239 Runnable runnable
= new Runnable() {
242 TreeUtil
.selectNode(myTree
, TreeUtil
.findNodeWithObject(myRoot
, list
));
244 myContentManager
.setSelectedContent(myContent
);
245 ToolWindow window
= ToolWindowManager
.getInstance(myProject
).getToolWindow(ChangesViewContentManager
.TOOLWINDOW_ID
);
246 if (!window
.isVisible()) {
247 window
.activate(null);
251 if (myUpdatePending
) {
252 myPostUpdateRunnable
= runnable
;
259 private class ShelfTree
extends Tree
implements TypeSafeDataProvider
{
260 public void calcData(DataKey key
, DataSink sink
) {
261 if (key
== SHELVED_CHANGELIST_KEY
) {
262 final Set
<ShelvedChangeList
> changeLists
= getSelectedLists(false);
264 if (changeLists
.size() > 0) {
265 sink
.put(SHELVED_CHANGELIST_KEY
, changeLists
.toArray(new ShelvedChangeList
[changeLists
.size()]));
268 else if (key
== SHELVED_RECYCLED_CHANGELIST_KEY
) {
269 final Set
<ShelvedChangeList
> changeLists
= getSelectedLists(true);
271 if (changeLists
.size() > 0) {
272 sink
.put(SHELVED_RECYCLED_CHANGELIST_KEY
, changeLists
.toArray(new ShelvedChangeList
[changeLists
.size()]));
275 else if (key
== SHELVED_CHANGE_KEY
) {
276 sink
.put(SHELVED_CHANGE_KEY
, TreeUtil
.collectSelectedObjectsOfType(this, ShelvedChange
.class));
278 else if (key
== SHELVED_BINARY_FILE_KEY
) {
279 sink
.put(SHELVED_BINARY_FILE_KEY
, TreeUtil
.collectSelectedObjectsOfType(this, ShelvedBinaryFile
.class));
281 else if (key
== VcsDataKeys
.CHANGES
) {
282 List
<ShelvedChange
> shelvedChanges
= TreeUtil
.collectSelectedObjectsOfType(this, ShelvedChange
.class);
283 if (shelvedChanges
.size() > 0) {
284 Change
[] changes
= new Change
[shelvedChanges
.size()];
285 for(int i
=0; i
<shelvedChanges
.size(); i
++) {
286 changes
[i
] = shelvedChanges
.get(i
).getChange(myProject
);
288 sink
.put(VcsDataKeys
.CHANGES
, changes
);
291 final List
<ShelvedChangeList
> changeLists
= TreeUtil
.collectSelectedObjectsOfType(this, ShelvedChangeList
.class);
292 if (changeLists
.size() > 0) {
293 List
<Change
> changes
= new ArrayList
<Change
>();
294 for(ShelvedChangeList changeList
: changeLists
) {
295 shelvedChanges
= changeList
.getChanges();
296 for(ShelvedChange shelvedChange
: shelvedChanges
) {
297 changes
.add(shelvedChange
.getChange(myProject
));
300 sink
.put(VcsDataKeys
.CHANGES
, changes
.toArray(new Change
[changes
.size()]));
304 else if (key
== PlatformDataKeys
.DELETE_ELEMENT_PROVIDER
) {
305 sink
.put(PlatformDataKeys
.DELETE_ELEMENT_PROVIDER
, myDeleteProvider
);
309 private Set
<ShelvedChangeList
> getSelectedLists(final boolean recycled
) {
310 final TreePath
[] selections
= getSelectionPaths();
311 final Set
<ShelvedChangeList
> changeLists
= new HashSet
<ShelvedChangeList
>();
312 if (selections
!= null) {
313 for(TreePath path
: selections
) {
314 if (path
.getPathCount() >= 2) {
315 DefaultMutableTreeNode node
= (DefaultMutableTreeNode
) path
.getPathComponent(1);
316 if (node
.getUserObject() instanceof ShelvedChangeList
) {
317 final ShelvedChangeList list
= (ShelvedChangeList
)node
.getUserObject();
318 if (((! recycled
) && (! list
.isRecycled())) ||
319 (recycled
&& list
.isRecycled())) {
320 changeLists
.add(list
);
330 private final static class ShelvedFilePatchComparator
implements Comparator
<Object
> {
331 private final static ShelvedFilePatchComparator ourInstance
= new ShelvedFilePatchComparator();
333 public static ShelvedFilePatchComparator
getInstance() {
337 public int compare(final Object o1
, final Object o2
) {
338 final String path1
= getPath(o1
);
339 final String path2
= getPath(o2
);
340 // case-insensitive; as in local changes
341 if (path1
== null) return -1;
342 if (path2
== null) return 1;
343 return path1
.compareToIgnoreCase(path2
);
346 private static String
getPath(final Object patch
) {
348 if (patch
instanceof ShelvedBinaryFile
) {
349 final ShelvedBinaryFile binaryFile
= (ShelvedBinaryFile
) patch
;
350 path
= binaryFile
.BEFORE_PATH
;
351 path
= (path
== null) ? binaryFile
.AFTER_PATH
: path
;
352 } else if (patch
instanceof ShelvedChange
) {
353 final ShelvedChange shelvedChange
= (ShelvedChange
)patch
;
354 path
= shelvedChange
.getBeforePath().replace('/', File
.separatorChar
);
359 final int pos
= path
.lastIndexOf(File
.separatorChar
);
360 return (pos
>= 0) ? path
.substring(pos
+ 1) : path
;
364 private static class ShelfTreeCellRenderer
extends ColoredTreeCellRenderer
{
365 private final IssueLinkRenderer myIssueLinkRenderer
;
366 private final Map
<Pair
<String
, String
>, String
> myMoveRenameInfo
;
368 public ShelfTreeCellRenderer(Project project
, final Map
<Pair
<String
, String
>, String
> moveRenameInfo
) {
369 myMoveRenameInfo
= moveRenameInfo
;
370 myIssueLinkRenderer
= new IssueLinkRenderer(project
, this);
373 public void customizeCellRenderer(JTree tree
, Object value
, boolean selected
, boolean expanded
, boolean leaf
, int row
, boolean hasFocus
) {
374 DefaultMutableTreeNode node
= (DefaultMutableTreeNode
) value
;
375 Object nodeValue
= node
.getUserObject();
376 if (nodeValue
instanceof ShelvedChangeList
) {
377 ShelvedChangeList changeListData
= (ShelvedChangeList
) nodeValue
;
378 if (changeListData
.isRecycled()) {
379 myIssueLinkRenderer
.appendTextWithLinks(changeListData
.DESCRIPTION
, SimpleTextAttributes
.GRAYED_BOLD_ATTRIBUTES
);
381 myIssueLinkRenderer
.appendTextWithLinks(changeListData
.DESCRIPTION
);
383 final int count
= node
.getChildCount();
384 final String numFilesText
= " (" + count
+ ((count
== 1) ?
" file) " : " files) ");
385 append(numFilesText
, SimpleTextAttributes
.GRAY_ITALIC_ATTRIBUTES
);
387 final String date
= SimpleDateFormat
.getDateTimeInstance(SimpleDateFormat
.SHORT
, SimpleDateFormat
.SHORT
).format(changeListData
.DATE
);
388 append(" (" + date
+ ")", SimpleTextAttributes
.GRAYED_ATTRIBUTES
);
389 setIcon(StdFileTypes
.PATCH
.getIcon());
391 else if (nodeValue
instanceof ShelvedChange
) {
392 ShelvedChange change
= (ShelvedChange
) nodeValue
;
393 final String movedMessage
= myMoveRenameInfo
.get(new Pair
<String
, String
>(change
.getBeforePath(), change
.getAfterPath()));
394 renderFileName(change
.getBeforePath(), change
.getFileStatus(), movedMessage
);
396 else if (nodeValue
instanceof ShelvedBinaryFile
) {
397 ShelvedBinaryFile binaryFile
= (ShelvedBinaryFile
) nodeValue
;
398 String path
= binaryFile
.BEFORE_PATH
;
400 path
= binaryFile
.AFTER_PATH
;
402 final String movedMessage
= myMoveRenameInfo
.get(new Pair
<String
, String
>(binaryFile
.BEFORE_PATH
, binaryFile
.AFTER_PATH
));
403 renderFileName(path
, binaryFile
.getFileStatus(), movedMessage
);
407 private void renderFileName(String path
, final FileStatus fileStatus
, final String movedMessage
) {
408 path
= path
.replace('/', File
.separatorChar
);
409 int pos
= path
.lastIndexOf(File
.separatorChar
);
413 directory
= path
.substring(0, pos
).replace(File
.separatorChar
, File
.separatorChar
);
414 fileName
= path
.substring(pos
+1);
417 directory
= "<project root>";
420 append(fileName
, new SimpleTextAttributes(SimpleTextAttributes
.STYLE_PLAIN
, fileStatus
.getColor()));
421 if (movedMessage
!= null) {
422 append(movedMessage
, SimpleTextAttributes
.REGULAR_ATTRIBUTES
);
424 append(" ("+ directory
+ ")", SimpleTextAttributes
.GRAYED_ATTRIBUTES
);
425 setIcon(FileTypeManager
.getInstance().getFileTypeByFileName(fileName
).getIcon());
429 private class MyChangeListDeleteProvider
implements DeleteProvider
{
430 public void deleteElement(DataContext dataContext
) {
431 //noinspection unchecked
432 final List
<ShelvedChangeList
> shelvedChangeLists
= getLists(dataContext
);
433 if (shelvedChangeLists
.isEmpty()) return;
434 String message
= (shelvedChangeLists
.size() == 1)
435 ? VcsBundle
.message("shelve.changes.delete.confirm", shelvedChangeLists
.get(0).DESCRIPTION
)
436 : VcsBundle
.message("shelve.changes.delete.multiple.confirm", shelvedChangeLists
.size());
437 int rc
= Messages
.showOkCancelDialog(myProject
, message
, VcsBundle
.message("shelvedChanges.delete.title"), Messages
.getWarningIcon());
439 for(ShelvedChangeList changeList
: shelvedChangeLists
) {
440 ShelveChangesManager
.getInstance(myProject
).deleteChangeList(changeList
);
444 public boolean canDeleteElement(DataContext dataContext
) {
445 //noinspection unchecked
446 return ! getLists(dataContext
).isEmpty();
449 private List
<ShelvedChangeList
> getLists(final DataContext dataContext
) {
450 final ShelvedChangeList
[] shelved
= SHELVED_CHANGELIST_KEY
.getData(dataContext
);
451 final ShelvedChangeList
[] recycled
= SHELVED_RECYCLED_CHANGELIST_KEY
.getData(dataContext
);
453 final List
<ShelvedChangeList
> shelvedChangeLists
= (shelved
== null && recycled
== null) ?
454 Collections
.<ShelvedChangeList
>emptyList() : new ArrayList
<ShelvedChangeList
>();
455 if (shelved
!= null) {
456 shelvedChangeLists
.addAll(Arrays
.asList(shelved
));
458 if (recycled
!= null) {
459 shelvedChangeLists
.addAll(Arrays
.asList(recycled
));
461 return shelvedChangeLists
;
465 private class MyChangesDeleteProvider
implements DeleteProvider
{
466 public void deleteElement(DataContext dataContext
) {
467 final ShelvedChangeList
[] shelved
= SHELVED_CHANGELIST_KEY
.getData(dataContext
);
468 if (shelved
== null || (shelved
.length
!= 1)) return;
469 final List
<ShelvedChange
> changes
= SHELVED_CHANGE_KEY
.getData(dataContext
);
470 final List
<ShelvedBinaryFile
> binaryFiles
= SHELVED_BINARY_FILE_KEY
.getData(dataContext
);
472 final ShelvedChangeList list
= shelved
[0];
474 final String message
= VcsBundle
.message("shelve.changes.delete.files.from.list", (changes
== null ?
0 : changes
.size()) +
475 (binaryFiles
== null ?
0 : binaryFiles
.size()));
476 int rc
= Messages
.showOkCancelDialog(myProject
, message
, VcsBundle
.message("shelve.changes.delete.files.from.list.title"), Messages
.getWarningIcon());
479 final ArrayList
<ShelvedBinaryFile
> oldBinaries
= new ArrayList
<ShelvedBinaryFile
>(list
.getBinaryFiles());
480 final ArrayList
<ShelvedChange
> oldChanges
= new ArrayList
<ShelvedChange
>(list
.getChanges());
482 oldBinaries
.removeAll(binaryFiles
);
483 oldChanges
.removeAll(changes
);
485 final List
<FilePatch
> patches
= new ArrayList
<FilePatch
>();
486 final List
<VcsException
> exceptions
= new ArrayList
<VcsException
>();
487 for (ShelvedChange change
: oldChanges
) {
489 patches
.add(change
.loadFilePatch());
491 catch (IOException e
) {
492 //noinspection ThrowableInstanceNeverThrown
493 exceptions
.add(new VcsException(e
));
495 catch (PatchSyntaxException e
) {
496 //noinspection ThrowableInstanceNeverThrown
497 exceptions
.add(new VcsException(e
));
501 myShelveChangesManager
.saveRemainingPatches(list
, patches
, oldBinaries
);
503 if (! exceptions
.isEmpty()) {
504 String title
= list
.DESCRIPTION
== null ?
"" : list
.DESCRIPTION
;
505 title
= title
.substring(0, Math
.min(10, list
.DESCRIPTION
.length()));
506 AbstractVcsHelper
.getInstance(myProject
).showErrors(exceptions
, "Deleting files from '" + title
+ "'");
510 public boolean canDeleteElement(DataContext dataContext
) {
511 final ShelvedChangeList
[] shelved
= SHELVED_CHANGELIST_KEY
.getData(dataContext
);
512 if (shelved
== null || (shelved
.length
!= 1)) return false;
513 final List
<ShelvedChange
> changes
= SHELVED_CHANGE_KEY
.getData(dataContext
);
514 if (changes
!= null && (! changes
.isEmpty())) return true;
515 final List
<ShelvedBinaryFile
> binaryFiles
= SHELVED_BINARY_FILE_KEY
.getData(dataContext
);
516 return (binaryFiles
!= null && (! binaryFiles
.isEmpty()));
520 private class ShelvedChangeDeleteProvider
implements DeleteProvider
{
521 private final List
<DeleteProvider
> myProviders
;
523 private ShelvedChangeDeleteProvider() {
524 myProviders
= Arrays
.asList(new MyChangesDeleteProvider(), new MyChangeListDeleteProvider());
528 private DeleteProvider
selectDelegate(final DataContext dataContext
) {
529 for (DeleteProvider provider
: myProviders
) {
530 if (provider
.canDeleteElement(dataContext
)) {
537 public void deleteElement(DataContext dataContext
) {
538 final DeleteProvider delegate
= selectDelegate(dataContext
);
539 if (delegate
!= null) {
540 delegate
.deleteElement(dataContext
);
544 public boolean canDeleteElement(DataContext dataContext
) {
545 return selectDelegate(dataContext
) != null;