EditSource action improved for commit and push dialog;

* close appropriate model dialog after action performed if needed;
* invoke later deprecated call changed;
* action constructor now depends on parent component instead of dialog wrapper
This commit is contained in:
Nadya Zabrodina
2014-12-15 15:36:21 +03:00
parent 27cfbfb589
commit b2a0835c00
3 changed files with 200 additions and 194 deletions
@@ -23,6 +23,7 @@ import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.TextRevisionNumber;
import com.intellij.openapi.vcs.changes.committed.CommittedChangesTreeBrowser;
import com.intellij.openapi.vcs.changes.ui.ChangesBrowser;
import com.intellij.openapi.vcs.changes.ui.EditSourceForDialogAction;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.ui.*;
import com.intellij.util.ArrayUtil;
@@ -181,7 +182,9 @@ public class PushLog extends JPanel implements TypeSafeDataProvider {
new ChangesBrowser(project, null, Collections.<Change>emptyList(), null, false, true, null, ChangesBrowser.MyUseCase.LOCAL_CHANGES,
null);
myChangesBrowser.getDiffAction().registerCustomShortcutSet(CommonShortcuts.getDiff(), myTree);
myChangesBrowser.addToolbarAction(ActionManager.getInstance().getAction(IdeActions.ACTION_EDIT_SOURCE));
final EditSourceForDialogAction editSourceAction = new EditSourceForDialogAction(myChangesBrowser);
editSourceAction.registerCustomShortcutSet(CommonShortcuts.getEditSource(), myChangesBrowser);
myChangesBrowser.addToolbarAction(editSourceAction);
setDefaultEmptyText();
Splitter splitter = new Splitter(false, 0.7f);
@@ -196,17 +199,6 @@ public class PushLog extends JPanel implements TypeSafeDataProvider {
myTree.setRowHeight(0);
}
private void updateChangesView() {
List<CommitNode> commitNodes = getSelectedCommitNodes();
if (!commitNodes.isEmpty()) {
myChangesBrowser.getViewer().setEmptyText("No differences");
}
else {
setDefaultEmptyText();
}
myChangesBrowser.setChangesToDisplay(collectAllChanges(commitNodes));
}
@NotNull
private static List<Change> collectAllChanges(@NotNull List<CommitNode> commitNodes) {
return CommittedChangesTreeBrowser.zipChanges(collectChanges(commitNodes));
@@ -251,6 +243,27 @@ public class PushLog extends JPanel implements TypeSafeDataProvider {
return nodes;
}
@NotNull
private static List<Integer> getSortedRows(@NotNull int[] rows) {
List<Integer> sorted = ContainerUtil.newArrayList();
for (int row : rows) {
sorted.add(row);
}
Collections.sort(sorted, Collections.reverseOrder());
return sorted;
}
private void updateChangesView() {
List<CommitNode> commitNodes = getSelectedCommitNodes();
if (!commitNodes.isEmpty()) {
myChangesBrowser.getViewer().setEmptyText("No differences");
}
else {
setDefaultEmptyText();
}
myChangesBrowser.setChangesToDisplay(collectAllChanges(commitNodes));
}
private void setDefaultEmptyText() {
myChangesBrowser.getViewer().setEmptyText("No commits selected");
}
@@ -284,16 +297,6 @@ public class PushLog extends JPanel implements TypeSafeDataProvider {
return ContainerUtil.emptyList();
}
@NotNull
private static List<Integer> getSortedRows(@NotNull int[] rows) {
List<Integer> sorted = ContainerUtil.newArrayList();
for (int row : rows) {
sorted.add(row);
}
Collections.sort(sorted, Collections.reverseOrder());
return sorted;
}
@NotNull
private List<DefaultMutableTreeNode> getNodesForRows(@NotNull List<Integer> rows) {
List<DefaultMutableTreeNode> nodes = ContainerUtil.newArrayList();
@@ -339,68 +342,6 @@ public class PushLog extends JPanel implements TypeSafeDataProvider {
}
}
private class MyTreeCellEditor extends AbstractCellEditor implements TreeCellEditor {
private RepositoryWithBranchPanel myValue;
@Override
public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row) {
RepositoryWithBranchPanel panel = (RepositoryWithBranchPanel)((DefaultMutableTreeNode)value).getUserObject();
myValue = panel;
myTree.firePropertyChange(PushLogTreeUtil.EDIT_MODE_PROP, false, true);
return panel.getTreeCellEditorComponent(tree, value, isSelected, expanded, leaf, row, true);
}
@Override
public boolean isCellEditable(EventObject anEvent) {
if (anEvent instanceof MouseEvent) {
MouseEvent me = ((MouseEvent)anEvent);
final TreePath path = myTree.getClosestPathForLocation(me.getX(), me.getY());
final int row = myTree.getRowForLocation(me.getX(), me.getY());
myTree.getCellRenderer().getTreeCellRendererComponent(myTree, path.getLastPathComponent(), false, false, true, row, true);
Object tag = me.getClickCount() >= 1
? PushLogTreeUtil.getTagAtForRenderer(myTreeCellRenderer, me)
: null;
return tag instanceof VcsEditableComponent;
}
//if keyboard event - then anEvent will be null =( See BasicTreeUi
TreePath treePath = myTree.getAnchorSelectionPath();
//there is no selection path if we start editing during initial validation//
if (treePath == null) return true;
Object treeNode = treePath.getLastPathComponent();
return treeNode instanceof EditableTreeNode;
}
public Object getCellEditorValue() {
return myValue;
}
}
private static class MyTreeCellRenderer extends CheckboxTree.CheckboxTreeCellRenderer {
@Override
public void customizeRenderer(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
if (!(value instanceof DefaultMutableTreeNode)) {
return;
}
myCheckbox.setBorder(null); //checkBox may have no border by default, but insets are not null,
// it depends on LaF, OS and isItRenderedPane, see com.intellij.ide.ui.laf.darcula.ui.DarculaCheckBoxBorder.
// null border works as expected always.
if (value instanceof RepositoryNode) {
//todo simplify, remove instance of
myCheckbox.setVisible(((RepositoryNode)value).isCheckboxVisible());
}
Object userObject = ((DefaultMutableTreeNode)value).getUserObject();
ColoredTreeCellRenderer renderer = getTextRenderer();
if (value instanceof CustomRenderedTreeNode) {
((CustomRenderedTreeNode)value).render(renderer);
}
else {
renderer.append(userObject == null ? "" : userObject.toString());
}
}
}
public void setChildren(@NotNull DefaultMutableTreeNode parentNode,
@NotNull Collection<? extends DefaultMutableTreeNode> childrenNodes) {
parentNode.removeAllChildren();
@@ -445,6 +386,68 @@ public class PushLog extends JPanel implements TypeSafeDataProvider {
}
}
private static class MyTreeCellRenderer extends CheckboxTree.CheckboxTreeCellRenderer {
@Override
public void customizeRenderer(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
if (!(value instanceof DefaultMutableTreeNode)) {
return;
}
myCheckbox.setBorder(null); //checkBox may have no border by default, but insets are not null,
// it depends on LaF, OS and isItRenderedPane, see com.intellij.ide.ui.laf.darcula.ui.DarculaCheckBoxBorder.
// null border works as expected always.
if (value instanceof RepositoryNode) {
//todo simplify, remove instance of
myCheckbox.setVisible(((RepositoryNode)value).isCheckboxVisible());
}
Object userObject = ((DefaultMutableTreeNode)value).getUserObject();
ColoredTreeCellRenderer renderer = getTextRenderer();
if (value instanceof CustomRenderedTreeNode) {
((CustomRenderedTreeNode)value).render(renderer);
}
else {
renderer.append(userObject == null ? "" : userObject.toString());
}
}
}
private class MyTreeCellEditor extends AbstractCellEditor implements TreeCellEditor {
private RepositoryWithBranchPanel myValue;
@Override
public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row) {
RepositoryWithBranchPanel panel = (RepositoryWithBranchPanel)((DefaultMutableTreeNode)value).getUserObject();
myValue = panel;
myTree.firePropertyChange(PushLogTreeUtil.EDIT_MODE_PROP, false, true);
return panel.getTreeCellEditorComponent(tree, value, isSelected, expanded, leaf, row, true);
}
@Override
public boolean isCellEditable(EventObject anEvent) {
if (anEvent instanceof MouseEvent) {
MouseEvent me = ((MouseEvent)anEvent);
final TreePath path = myTree.getClosestPathForLocation(me.getX(), me.getY());
final int row = myTree.getRowForLocation(me.getX(), me.getY());
myTree.getCellRenderer().getTreeCellRendererComponent(myTree, path.getLastPathComponent(), false, false, true, row, true);
Object tag = me.getClickCount() >= 1
? PushLogTreeUtil.getTagAtForRenderer(myTreeCellRenderer, me)
: null;
return tag instanceof VcsEditableComponent;
}
//if keyboard event - then anEvent will be null =( See BasicTreeUi
TreePath treePath = myTree.getAnchorSelectionPath();
//there is no selection path if we start editing during initial validation//
if (treePath == null) return true;
Object treeNode = treePath.getLastPathComponent();
return treeNode instanceof EditableTreeNode;
}
public Object getCellEditorValue() {
return myValue;
}
}
private class MyTreeUi extends WideSelectionTreeUI {
private final ComponentListener myTreeSizeListener = new ComponentAdapter() {
@@ -16,36 +16,41 @@
package com.intellij.openapi.vcs.changes.ui;
import com.intellij.icons.AllIcons;
import com.intellij.ide.actions.EditSourceAction;
import com.intellij.idea.ActionsBundle;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.pom.Navigatable;
import com.intellij.util.OpenSourceUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
public class EditSourceInCommitAction extends AnAction {
private final DialogWrapper myDialogWrapper;
public class EditSourceForDialogAction extends EditSourceAction {
@NotNull private final Component mySourceComponent;
public EditSourceInCommitAction(final DialogWrapper dialogWrapper) {
super(ActionsBundle.actionText("EditSource"),
ActionsBundle.actionDescription("EditSource"),
AllIcons.Actions.EditSource);
myDialogWrapper = dialogWrapper;
public EditSourceForDialogAction(@NotNull Component component) {
super();
Presentation presentation = getTemplatePresentation();
presentation.setText(ActionsBundle.actionText("EditSource"));
presentation.setIcon(AllIcons.Actions.EditSource);
presentation.setDescription(ActionsBundle.actionDescription("EditSource"));
mySourceComponent = component;
}
public void actionPerformed(AnActionEvent e) {
final Navigatable[] navigatableArray = e.getData(CommonDataKeys.NAVIGATABLE_ARRAY);
if (navigatableArray != null && navigatableArray.length > 0) {
SwingUtilities.invokeLater(new Runnable() {
ApplicationManager.getApplication().invokeLater(new Runnable() {
public void run() {
OpenSourceUtil.navigate(navigatableArray);
}
});
myDialogWrapper.doCancelAction();
DialogWrapper dialog = DialogWrapper.findInstance(mySourceComponent);
if (dialog != null && dialog.isModal()) {
dialog.doCancelAction();
}
}
}
}
@@ -55,12 +55,12 @@ public class MultipleChangeListBrowser extends ChangesBrowser {
private final ChangeListListener myChangeListListener = new MyChangeListListener();
private final boolean myShowingAllChangeLists;
private final EventDispatcher<SelectedListChangeListener> myDispatcher = EventDispatcher.create(SelectedListChangeListener.class);
private Collection<Change> myAllChanges;
private Map<Change, LocalChangeList> myChangeListsMap;
private final ChangesBrowserExtender myExtender;
private final Disposable myParentDisposable;
private final Runnable myRebuildListListener;
private Collection<Change> myAllChanges;
private Map<Change, LocalChangeList> myChangeListsMap;
private boolean myInRebuildList;
// todo terrible constructor
public MultipleChangeListBrowser(final Project project, final List<? extends ChangeList> changeLists, final List<Change> changes,
@@ -152,8 +152,6 @@ public class MultipleChangeListBrowser extends ChangesBrowser {
myDispatcher.getMulticaster().selectedListChanged();
}
private boolean myInRebuildList;
@Override
public void rebuildList() {
if (myInRebuildList) return;
@@ -235,9 +233,99 @@ public class MultipleChangeListBrowser extends ChangesBrowser {
return actions;
}
private void updateListsInChooser() {
Runnable runnable = new Runnable() {
public void run() {
if (myChangeListChooser != null && myShowingAllChangeLists) {
myChangeListChooser.updateLists(ChangeListManager.getInstance(myProject).getChangeListsCopy());
}
}
};
if (SwingUtilities.isEventDispatchThread()) {
runnable.run();
}
else {
ApplicationManager.getApplication().invokeLater(runnable, ModalityState.stateForComponent(MultipleChangeListBrowser.this));
}
}
private static class Extender implements ChangesBrowserExtender {
private final Project myProject;
private final MultipleChangeListBrowser myBrowser;
private final AnAction[] myAdditionalActions;
private Extender(final Project project, final MultipleChangeListBrowser browser, AnAction[] additionalActions) {
myProject = project;
myBrowser = browser;
myAdditionalActions = additionalActions;
}
public void addToolbarActions(final DialogWrapper dialogWrapper) {
final Icon icon = AllIcons.Actions.Refresh;
if (myBrowser.myChangesToDisplay == null) {
myBrowser.addToolbarAction(new AnAction("Refresh Changes") {
@Override
public void actionPerformed(AnActionEvent e) {
myBrowser.rebuildList();
}
@Override
public void update(AnActionEvent e) {
e.getPresentation().setIcon(icon);
}
});
}
RollbackDialogAction rollback = new RollbackDialogAction();
EmptyAction.setupAction(rollback, IdeActions.CHANGES_VIEW_ROLLBACK, myBrowser);
myBrowser.addToolbarAction(rollback);
final EditSourceForDialogAction editSourceAction = new EditSourceForDialogAction(myBrowser);
editSourceAction.registerCustomShortcutSet(CommonShortcuts.getEditSource(), myBrowser);
myBrowser.addToolbarAction(editSourceAction);
myBrowser.addToolbarAction(ActionManager.getInstance().getAction("Vcs.CheckinProjectToolbar"));
final List<AnAction> actions = AdditionalLocalChangeActionsInstaller.calculateActions(myProject, myBrowser.getAllChanges());
if (actions != null) {
for (AnAction action : actions) {
myBrowser.addToolbarAction(action);
}
}
if (myAdditionalActions != null && myAdditionalActions.length > 0) {
for (int i = 0; i < myAdditionalActions.length; i++) {
final AnAction action = myAdditionalActions[i];
myBrowser.addToolbarAction(action);
}
}
}
public void addSelectedListChangeListener(final SelectedListChangeListener listener) {
myBrowser.addSelectedListChangeListener(listener);
}
public Collection<AbstractVcs> getAffectedVcses() {
final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(myProject);
final Set<AbstractVcs> vcses = new HashSet<AbstractVcs>(Arrays.asList(vcsManager.getAllActiveVcss()));
final Set<AbstractVcs> result = new HashSet<AbstractVcs>();
for (Change change : myBrowser.myAllChanges) {
if (vcses.isEmpty()) break;
final AbstractVcs vcs = ChangesUtil.getVcsForChange(change, myBrowser.myProject);
if (vcs != null) {
result.add(vcs);
vcses.remove(vcs);
}
}
return result;
}
public List<Change> getCurrentIncludedChanges() {
return myBrowser.getCurrentIncludedChanges();
}
}
private class ChangeListChooser extends JPanel {
private final JComboBox myChooser;
private final static int MAX_LEN = 35;
private final JComboBox myChooser;
public ChangeListChooser(List<? extends ChangeList> lists) {
super(new BorderLayout(4, 2));
@@ -294,22 +382,6 @@ public class MultipleChangeListBrowser extends ChangesBrowser {
}
}
private void updateListsInChooser() {
Runnable runnable = new Runnable() {
public void run() {
if (myChangeListChooser != null && myShowingAllChangeLists) {
myChangeListChooser.updateLists(ChangeListManager.getInstance(myProject).getChangeListsCopy());
}
}
};
if (SwingUtilities.isEventDispatchThread()) {
runnable.run();
}
else {
ApplicationManager.getApplication().invokeLater(runnable, ModalityState.stateForComponent(MultipleChangeListBrowser.this));
}
}
private class MoveAction extends MoveChangesToAnotherListAction {
private final Change myChange;
@@ -321,78 +393,4 @@ public class MultipleChangeListBrowser extends ChangesBrowser {
askAndMove(myProject, Collections.singletonList(myChange), null);
}
}
private static class Extender implements ChangesBrowserExtender {
private final Project myProject;
private final MultipleChangeListBrowser myBrowser;
private final AnAction[] myAdditionalActions;
private Extender(final Project project, final MultipleChangeListBrowser browser, AnAction[] additionalActions) {
myProject = project;
myBrowser = browser;
myAdditionalActions = additionalActions;
}
public void addToolbarActions(final DialogWrapper dialogWrapper) {
final Icon icon = AllIcons.Actions.Refresh;
if (myBrowser.myChangesToDisplay == null) {
myBrowser.addToolbarAction(new AnAction("Refresh Changes") {
@Override
public void actionPerformed(AnActionEvent e) {
myBrowser.rebuildList();
}
@Override
public void update(AnActionEvent e) {
e.getPresentation().setIcon(icon);
}
});
}
RollbackDialogAction rollback = new RollbackDialogAction();
EmptyAction.setupAction(rollback, IdeActions.CHANGES_VIEW_ROLLBACK, myBrowser);
myBrowser.addToolbarAction(rollback);
final EditSourceInCommitAction editSourceAction = new EditSourceInCommitAction(dialogWrapper);
editSourceAction.registerCustomShortcutSet(CommonShortcuts.getEditSource(), myBrowser);
myBrowser.addToolbarAction(editSourceAction);
myBrowser.addToolbarAction(ActionManager.getInstance().getAction("Vcs.CheckinProjectToolbar"));
final List<AnAction> actions = AdditionalLocalChangeActionsInstaller.calculateActions(myProject, myBrowser.getAllChanges());
if (actions != null) {
for (AnAction action : actions) {
myBrowser.addToolbarAction(action);
}
}
if (myAdditionalActions != null && myAdditionalActions.length > 0) {
for (int i = 0; i < myAdditionalActions.length; i++) {
final AnAction action = myAdditionalActions[i];
myBrowser.addToolbarAction(action);
}
}
}
public void addSelectedListChangeListener(final SelectedListChangeListener listener) {
myBrowser.addSelectedListChangeListener(listener);
}
public Collection<AbstractVcs> getAffectedVcses() {
final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(myProject);
final Set<AbstractVcs> vcses = new HashSet<AbstractVcs>(Arrays.asList(vcsManager.getAllActiveVcss()));
final Set<AbstractVcs> result = new HashSet<AbstractVcs>();
for (Change change : myBrowser.myAllChanges) {
if (vcses.isEmpty()) break;
final AbstractVcs vcs = ChangesUtil.getVcsForChange(change, myBrowser.myProject);
if (vcs != null) {
result.add(vcs);
vcses.remove(vcs);
}
}
return result;
}
public List<Change> getCurrentIncludedChanges() {
return myBrowser.getCurrentIncludedChanges();
}
}
}