| /* |
| * Copyright 2000-2009 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.actions; |
| |
| import com.intellij.openapi.actionSystem.ActionManager; |
| import com.intellij.openapi.actionSystem.AnAction; |
| import com.intellij.openapi.diff.DiffRequest; |
| import com.intellij.openapi.diff.DiffTool; |
| import com.intellij.openapi.diff.DiffToolbar; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.ui.Messages; |
| import com.intellij.openapi.util.NullableFactory; |
| import com.intellij.openapi.vcs.VcsDataKeys; |
| import com.intellij.openapi.vcs.VcsException; |
| import com.intellij.openapi.vcs.changes.ChangeRequestChain; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| /** |
| * @author yole |
| */ |
| public class ChangeDiffRequest implements ChangeRequestChain { |
| @NotNull private final List<DiffRequestPresentable> mySteps; |
| private final boolean myShowFrame; |
| private int myIndex; |
| |
| private final DiffExtendUIFactory myActionsFactory; |
| |
| private final AnAction myPrevChangeAction; |
| private final AnAction myNextChangeAction; |
| private final Project myProject; |
| private final DiffChainContext myContext; |
| private final AnAction mySelectChangeAction; |
| |
| public ChangeDiffRequest(final Project project, @NotNull List<DiffRequestPresentable> steps, final DiffExtendUIFactory actionsFactory, |
| final boolean showFrame) { |
| myProject = project; |
| mySteps = steps; |
| myShowFrame = showFrame; |
| myContext = new DiffChainContext(); |
| |
| myIndex = 0; |
| myActionsFactory = actionsFactory; |
| |
| myPrevChangeAction = ActionManager.getInstance().getAction("Diff.PrevChange"); |
| myNextChangeAction = ActionManager.getInstance().getAction("Diff.NextChange"); |
| mySelectChangeAction = ActionManager.getInstance().getAction("Diff.SelectedChange"); |
| } |
| |
| @NotNull |
| @Override |
| public List<DiffRequestPresentable> getAllRequests() { |
| return mySteps; |
| } |
| |
| private void onEveryMove(final DiffRequest simpleRequest, final boolean showFrame) { |
| simpleRequest.passForDataContext(VcsDataKeys.DIFF_REQUEST_CHAIN, this); |
| if (showFrame) { |
| simpleRequest.addHint(DiffTool.HINT_SHOW_FRAME); |
| } |
| else { |
| simpleRequest.addHint(DiffTool.HINT_SHOW_MODAL_DIALOG); |
| } |
| if (mySteps.size() > 1) { |
| simpleRequest.addHint(DiffTool.HINT_ALLOW_NO_DIFFERENCES); |
| } |
| } |
| |
| public void quickCheckHaveStuff() throws VcsException { |
| if (mySteps.isEmpty()) { |
| throw new VcsException("Nothing selected to show diff"); |
| } |
| if (mySteps.size() == 1) { |
| mySteps.get(0).haveStuff(); |
| } |
| } |
| |
| @Nullable |
| public DiffRequest init(final int idx) { |
| if (idx < 0 || idx > (mySteps.size() - 1)) return null; |
| myIndex = idx - 1; |
| final DiffRequest result = moveForward(); |
| if (result == null && idx > 0) { |
| myIndex = -1; |
| return moveForward(); |
| } |
| return result; |
| } |
| |
| public boolean canMoveForward() { |
| return myIndex < (mySteps.size() - 1); |
| } |
| |
| public boolean canMoveBack() { |
| return myIndex > 0; |
| } |
| |
| @Nullable |
| public DiffRequest moveForward() { |
| return moveWithErrorReport(new MoveDirection() { |
| public boolean canMove() { |
| return canMoveForward(); |
| } |
| |
| public int direction() { |
| return 1; |
| } |
| }); |
| } |
| |
| @Nullable |
| @Override |
| public DiffRequest moveTo(DiffRequestPresentable presentable) { |
| int index = findRequest(presentable); |
| if (index == -1) { |
| return null; |
| } |
| |
| final List<String> errors = new ArrayList<String>(); |
| DiffRequestPresentable.MyResult result = moveImpl(presentable, errors); |
| showErrors(errors); |
| if (result == null) { |
| return null; |
| } |
| if (DiffPresentationReturnValue.removeFromList.equals(result.getReturnValue())) { |
| return null; |
| } |
| myIndex = index; |
| return result.getRequest(); |
| } |
| |
| @Nullable |
| @Override |
| public DiffRequestPresentable getCurrentRequest() { |
| if (myIndex < 0 || myIndex >= mySteps.size()) { |
| return null; |
| } |
| return mySteps.get(myIndex); |
| } |
| |
| private int findRequest(DiffRequestPresentable presentable) { |
| for (int i = 0; i < mySteps.size(); i++) { |
| DiffRequestPresentable step = mySteps.get(i); |
| if (step.equals(presentable)) { |
| return i; |
| } |
| } |
| return -1; |
| } |
| |
| @Nullable |
| private DiffRequest moveWithErrorReport(final MoveDirection moveDirection) { |
| final List<String> errors = new ArrayList<String>(); |
| final DiffRequest diffRequest = moveInc(moveDirection, errors); |
| showErrors(errors); |
| return diffRequest; |
| } |
| |
| @Nullable |
| private DiffRequestPresentable.MyResult moveImpl(DiffRequestPresentable requestPresentable, final List<String> errors) { |
| final DiffRequestPresentable.MyResult result = requestPresentable.step(myContext); |
| final DiffPresentationReturnValue returnValue = result.getReturnValue(); |
| if (DiffPresentationReturnValue.quit.equals(returnValue)) { |
| errors.addAll(result.getErrors()); |
| return null; |
| } |
| |
| if (DiffPresentationReturnValue.removeFromList.equals(returnValue)) { |
| mySteps.remove(requestPresentable); |
| errors.addAll(result.getErrors()); |
| return result; |
| } |
| |
| final DiffRequest request = result.getRequest(); |
| takeStuffFromFactory(request, requestPresentable.createActions(myActionsFactory)); |
| onEveryMove(request, myShowFrame); |
| return result; |
| } |
| |
| @Nullable |
| private DiffRequest moveInc(final MoveDirection moveDirection, final List<String> errors) { |
| while (moveDirection.canMove()) { |
| final int nextIdx = myIndex + moveDirection.direction(); |
| final DiffRequestPresentable diffRequestPresentable = mySteps.get(nextIdx); |
| |
| DiffRequestPresentable.MyResult result = moveImpl(diffRequestPresentable, errors); |
| if (result == null) { |
| return null; |
| } |
| if (DiffPresentationReturnValue.removeFromList.equals(result.getReturnValue())) { |
| if (moveDirection.direction() < 0) { |
| // our position moves to head |
| myIndex += moveDirection.direction(); |
| } |
| continue; |
| } |
| |
| myIndex = nextIdx; |
| return result.getRequest(); |
| } |
| return null; |
| } |
| |
| private void showErrors(final List<String> errors) { |
| if (errors.isEmpty()) return; |
| final StringBuilder sb = new StringBuilder("Following problems have occurred:\n\n"); |
| for (String error : errors) { |
| sb.append(error).append('\n'); |
| } |
| Messages.showErrorDialog(myProject, sb.toString(), "Show Diff"); |
| } |
| |
| private interface MoveDirection { |
| boolean canMove(); |
| int direction(); |
| } |
| |
| @Nullable |
| public DiffRequest moveBack() { |
| return moveWithErrorReport(new MoveDirection() { |
| public boolean canMove() { |
| return canMoveBack(); |
| } |
| |
| public int direction() { |
| return -1; |
| } |
| }); |
| } |
| |
| private void takeStuffFromFactory(final DiffRequest request, final List<? extends AnAction> actions) { |
| if (mySteps.size() > 1 || (myActionsFactory != null)) { |
| request.setToolbarAddons(new DiffRequest.ToolbarAddons() { |
| public void customize(final DiffToolbar toolbar) { |
| if (mySteps.size() > 1) { |
| toolbar.addSeparator(); |
| } |
| toolbar.addAction(myPrevChangeAction); |
| toolbar.addAction(myNextChangeAction); |
| toolbar.addAction(mySelectChangeAction); |
| |
| if (myActionsFactory != null) { |
| toolbar.addSeparator(); |
| for (AnAction action : actions) { |
| toolbar.addAction(action); |
| } |
| } |
| } |
| }); |
| } |
| |
| if (myActionsFactory != null) { |
| request.setBottomComponentFactory(new NullableFactory<JComponent>() { |
| public JComponent create() { |
| return myActionsFactory.createBottomComponent(); |
| } |
| }); |
| } |
| } |
| } |