/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsChangeDetailsManager.java
https://bitbucket.org/nbargnesi/idea · Java · 365 lines · 297 code · 45 blank · 23 comment · 36 complexity · bf97c08290f9c2ea77c43b7fa249bcfc MD5 · raw file
- /*
- * Copyright 2000-2011 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.
- */
- package com.intellij.openapi.vcs.changes;
- import com.intellij.openapi.Disposable;
- import com.intellij.openapi.components.ServiceManager;
- import com.intellij.openapi.diff.DiffBundle;
- import com.intellij.openapi.diff.DiffContent;
- import com.intellij.openapi.diff.DiffManager;
- import com.intellij.openapi.diff.DiffPanel;
- import com.intellij.openapi.diff.ex.DiffPanelEx;
- import com.intellij.openapi.diff.ex.DiffPanelOptions;
- import com.intellij.openapi.diff.impl.DiffPanelImpl;
- import com.intellij.openapi.extensions.Extensions;
- import com.intellij.openapi.progress.BackgroundTaskQueue;
- import com.intellij.openapi.project.Project;
- import com.intellij.openapi.util.Disposer;
- import com.intellij.openapi.util.Pair;
- import com.intellij.openapi.vcs.FilePath;
- import com.intellij.openapi.vcs.VcsException;
- import com.intellij.openapi.vcs.VcsKey;
- import com.intellij.openapi.vcs.changes.actions.ShowDiffAction;
- import com.intellij.openapi.vcs.history.ShortVcsRevisionNumber;
- import com.intellij.openapi.vcs.history.VcsRevisionNumber;
- import com.intellij.util.BeforeAfter;
- import com.intellij.util.containers.HashMap;
- import com.intellij.vcsUtil.UIVcsUtil;
- import org.jetbrains.annotations.Nullable;
- import javax.swing.*;
- import java.awt.*;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.List;
- import java.util.Map;
- /**
- * todo extract interface and create stub for dummy project
- * @author irengrig
- * Date: 6/15/11
- * Time: 5:36 PM
- */
- public class VcsChangeDetailsManager {
- private final List<VcsChangeDetailsProvider> myProviders = new ArrayList<VcsChangeDetailsProvider>();
- private final List<VcsChangeDetailsProvider> myDedicatedList;
- private final Project myProject;
- private final BackgroundTaskQueue myQueue;
- public VcsChangeDetailsManager(final Project project) {
- myProject = project;
- myQueue = new BackgroundTaskQueue(myProject, "Loading change details");
- myDedicatedList = new ArrayList<VcsChangeDetailsProvider>();
- myDedicatedList.add(new BinaryDetailsProviderNew(project));
- myDedicatedList.add(new FragmentedDiffDetailsProvider(myProject));
- VcsChangeDetailsProvider[] extensions = Extensions.getExtensions(VcsChangeDetailsProvider.EP_NAME, myProject);
- myProviders.addAll(Arrays.asList(extensions));
- Disposer.register(project, new Disposable() {
- @Override
- public void dispose() {
- myQueue.clear();
- }
- });
- }
- public boolean canComment(final Change change) {
- for (VcsChangeDetailsProvider provider : myDedicatedList) {
- if (provider.canComment(change)) return true;
- }
- for (VcsChangeDetailsProvider provider : myProviders) {
- if (provider.canComment(change)) return true;
- }
- return false;
- }
- @Nullable
- public RefreshablePanel getPanel(final Change change, JComponent parent) {
- final List<Pair<String, RefreshablePanel>> panels = new ArrayList<Pair<String, RefreshablePanel>>();
- for (VcsChangeDetailsProvider convertor : myDedicatedList) {
- if (! convertor.canComment(change)) continue;
- RefreshablePanel panel = convertor.comment(change, parent, myQueue);
- if (panel != null) {
- panels.add(new Pair<String, RefreshablePanel>("Diff", panel));
- break; // only one of dedicated for now
- }
- }
- for (VcsChangeDetailsProvider provider : myProviders) {
- if (provider.canComment(change)) {
- RefreshablePanel panel = provider.comment(change, parent, myQueue);
- if (panel != null) {
- panels.add(new Pair<String, RefreshablePanel>(provider.getName(), panel));
- }
- }
- }
- if (! panels.isEmpty()) {
- if (panels.size() == 1) {
- return panels.get(0).getSecond();
- } else {
- TabbedRefreshablePanel tabbedRefreshablePanel = new TabbedRefreshablePanel();
- for (Pair<String, RefreshablePanel> panel : panels) {
- tabbedRefreshablePanel.addTab(panel.getFirst(), panel.getSecond());
- }
- return tabbedRefreshablePanel;
- }
- }
- return null;
- }
- public static VcsChangeDetailsManager getInstance(Project project) {
- return ServiceManager.getService(project, VcsChangeDetailsManager.class);
- }
- private static class BinaryDetailsProviderNew implements VcsChangeDetailsProvider {
- private final Project myProject;
- private BinaryDetailsProviderNew(Project project) {
- myProject = project;
- }
- @Override
- public String getName() {
- return "Contents Diff";
- }
- @Override
- public boolean canComment(Change change) {
- return canBeShownInBinaryDiff(change, myProject);
- }
- @Override
- public RefreshablePanel comment(Change change, JComponent parent, BackgroundTaskQueue queue) {
- return new BinaryDiffDetailsPanel(myProject, queue, change);
- }
- }
- private static boolean canBeShownInBinaryDiff(Change change, final Project project) {
- FilePath path = ChangesUtil.getFilePath(change);
- if (path != null && path.isDirectory()) return false;
- if (change.isTreeConflict() || change.isPhantom()) return false;
- return ShowDiffAction.isBinaryChangeAndCanShow(project, change);
- }
- private static class BinaryDiffDetailsPanel extends AbstractRefreshablePanel<ValueWithVcsException<List<BeforeAfter<DiffContent>>>> {
- private final BinaryDiffRequestFromChange myRequestFromChange;
- private final Project myProject;
- private final ChangeListManager myChangeListManager;
- private final FilePath myFilePath;
- private Change myChange;
- private final DiffPanel myPanel;
- private BinaryDiffDetailsPanel(Project project, BackgroundTaskQueue queue, final Change change) {
- super(project, "Loading change content", queue);
- myProject = project;
- myFilePath = ChangesUtil.getFilePath(change);
- myRequestFromChange = new BinaryDiffRequestFromChange(myProject);
- myChangeListManager = ChangeListManager.getInstance(myProject);
- myPanel = DiffManager.getInstance().createDiffPanel(null, myProject,this);
- myPanel.enableToolbar(false);
- myPanel.removeStatusBar();
- DiffPanelOptions o = ((DiffPanelEx)myPanel).getOptions();
- o.setRequestFocusOnNewContent(false);
- }
- @Override
- public boolean isStillValid(Change data) {
- return canBeShownInBinaryDiff(data, myProject);
- }
- @Override
- protected void refreshPresentation() {
- }
- @Override
- protected ValueWithVcsException<List<BeforeAfter<DiffContent>>> loadImpl() throws VcsException {
- myChange = myChangeListManager.getChange(myFilePath);
- if (myChange == null) {
- return null;
- }
- return new ValueWithVcsException<List<BeforeAfter<DiffContent>>>() {
- @Override
- protected List<BeforeAfter<DiffContent>> computeImpl() throws VcsException {
- return myRequestFromChange.createRequestForChange(myChange, 0);
- }
- };
- }
- @Override
- protected JPanel dataToPresentation(ValueWithVcsException<List<BeforeAfter<DiffContent>>> value) {
- if (value == null) return noDifferences();
- final List<BeforeAfter<DiffContent>> contents;
- try {
- contents = value.get();
- if (contents == null) throw new VcsException("Can not load content");
- }
- catch (VcsException e) {
- return UIVcsUtil.errorPanel(e.getMessage(), true);
- }
- if (contents.isEmpty()) return noDifferences();
- assert contents.size() == 1;
- myPanel.setContents(contents.get(0).getBefore(), contents.get(0).getAfter());
- ((DiffPanelImpl)myPanel).getOptions().setRequestFocusOnNewContent(false);
- final JPanel wholeWrapper = new JPanel(new BorderLayout());
- final JPanel topPanel = new JPanel(new BorderLayout());
- final JPanel wrapper = new JPanel();
- final BoxLayout boxLayout = new BoxLayout(wrapper, BoxLayout.X_AXIS);
- wrapper.setLayout(boxLayout);
- final JLabel label = new JLabel(changeDescription(myChange));
- label.setBorder(BorderFactory.createEmptyBorder(1,2,0,0));
- wrapper.add(label);
- topPanel.add(wrapper, BorderLayout.CENTER);
- wholeWrapper.add(topPanel, BorderLayout.NORTH);
- //wholeWrapper.add(new JBScrollPane(panel.getComponent()), BorderLayout.CENTER);
- wholeWrapper.add(myPanel.getComponent(), BorderLayout.CENTER);
- return wholeWrapper;
- }
- @Override
- protected void disposeImpl() {
- }
- @Override
- public void away() {
- //
- }
- }
- private static JPanel noDifferences() {
- return UIVcsUtil.errorPanel(DiffBundle.message("diff.contents.have.differences.only.in.line.separators.message.text"), false);
- }
- private static class FragmentedDiffDetailsProvider implements VcsChangeDetailsProvider {
- private final Project myProject;
- private FragmentedDiffDetailsProvider(Project project) {
- myProject = project;
- }
- @Override
- public String getName() {
- return "Contents Diff";
- }
- @Override
- public boolean canComment(Change change) {
- return FragmentedDiffRequestFromChange.canCreateRequest(change);
- }
- @Override
- public RefreshablePanel comment(Change change, JComponent parent, BackgroundTaskQueue queue) {
- return new FragmentedDiffDetailsPanel(myProject, queue, change, parent);
- }
- }
- private static class FragmentedDiffDetailsPanel extends AbstractRefreshablePanel<ValueWithVcsException<PreparedFragmentedContent>> {
- private final FragmentedDiffRequestFromChange myRequestFromChange;
- private final FilePath myFilePath;
- private final ChangeListManager myChangeListManager;
- private final ChangesFragmentedDiffPanel myDiffPanel;
- private final Project myProject;
- private FragmentedDiffDetailsPanel(Project project, BackgroundTaskQueue queue, final Change change, JComponent parent) {
- super(project, "Loading change content", queue);
- myProject = project;
- myFilePath = ChangesUtil.getFilePath(change);
- myRequestFromChange = new FragmentedDiffRequestFromChange(project);
- myChangeListManager = ChangeListManager.getInstance(project);
- myDiffPanel = new ChangesFragmentedDiffPanel(project, changeDescription(change), parent);
- myDiffPanel.buildUi();
- }
- @Override
- protected void refreshPresentation() {
- myDiffPanel.refreshPresentation();
- }
- @Override
- public boolean isStillValid(Change data) {
- return FragmentedDiffRequestFromChange.canCreateRequest(data);
- }
- @Override
- protected ValueWithVcsException<PreparedFragmentedContent> loadImpl() throws VcsException {
- return new ValueWithVcsException<PreparedFragmentedContent>() {
- @Override
- protected PreparedFragmentedContent computeImpl() throws VcsException {
- final Change change = myChangeListManager.getChange(myFilePath);
- if (change == null) {
- return null;
- }
- myDiffPanel.setTitle(changeDescription(change));
- return myRequestFromChange.getRanges(change);
- }
- };
- }
- @Override
- protected JPanel dataToPresentation(ValueWithVcsException<PreparedFragmentedContent> value) {
- final PreparedFragmentedContent requestForChange;
- try {
- requestForChange = value.get();
- if (requestForChange == null) return noDifferences();
- if (requestForChange.isEmpty()) {
- return noDifferences();
- }
- }
- catch (VcsException e) {
- return UIVcsUtil.errorPanel(e.getMessage(), true);
- }
- myDiffPanel.refreshData(requestForChange);
- return myDiffPanel.getPanel();
- }
- @Override
- protected void disposeImpl() {
- Disposer.dispose(myDiffPanel);
- }
- @Override
- public boolean refreshDataSynch() {
- try {
- myTicket.increment();
- ValueWithVcsException<PreparedFragmentedContent> exception = loadImpl();
- dataToPresentation(exception);
- }
- catch (VcsException e) {
- return false;
- }
- return true;
- }
- @Override
- public void away() {
- myDiffPanel.away();
- }
- }
- private static String changeDescription(Change o) {
- return ChangesUtil.getFilePath(o).getName() + " (" + (o.getBeforeRevision() == null ? "New" : beforeRevisionText(o)) + ")";
- }
- private static String beforeRevisionText(Change o) {
- VcsRevisionNumber revisionNumber = o.getBeforeRevision().getRevisionNumber();
- return revisionNumber instanceof ShortVcsRevisionNumber ? ((ShortVcsRevisionNumber) revisionNumber).toShortString() :
- revisionNumber.asString();
- }
- }