|
What this is
Other links
The source code
/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is NetBeans. The Initial Developer of the Original
* Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
* Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.modules.merge.builtin.visualizer;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
import java.io.Reader;
import java.io.Writer;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Set;
import java.util.HashSet;
import org.openide.util.NbBundle;
import org.netbeans.api.diff.Difference;
import org.netbeans.api.diff.StreamSource;
/**
* This class controls the merge process.
*
* @author Martin Entlicher
*/
public class MergeControl extends Object implements ActionListener, VetoableChangeListener {
private Color colorUnresolvedConflict;
private Color colorResolvedConflict;
private Color colorOtherConflict;
private MergePanel panel;
private Difference[] diffs;
/** The shift of differences */
private int[][] diffShifts;
/** The current diff */
private int currentDiffLine = 0;
private int[] resultDiffLocations;
private Set resolvedConflicts = new HashSet();
private StreamSource resultSource;
/** Creates a new instance of MergeControl */
public MergeControl(MergePanel panel) {
this.panel = panel;
}
public void initialize(Difference[] diffs, StreamSource source1,
StreamSource source2, StreamSource result,
Color colorUnresolvedConflict, Color colorResolvedConflict,
Color colorOtherConflict) {
this.diffs = diffs;
this.diffShifts = new int[diffs.length][2];
this.resultDiffLocations = new int[diffs.length];
panel.setMimeType1(source1.getMIMEType());
panel.setMimeType2(source2.getMIMEType());
panel.setMimeType3(result.getMIMEType());
panel.setSource1Title(source1.getTitle());
panel.setSource2Title(source2.getTitle());
panel.setResultSourceTitle(result.getTitle());
panel.setName(source1.getName());
try {
panel.setSource1(source1.createReader());
panel.setSource2(source2.createReader());
panel.setResultSource(new java.io.StringReader(""));
} catch (IOException ioex) {
org.openide.ErrorManager.getDefault().notify(ioex);
}
this.colorUnresolvedConflict = colorUnresolvedConflict;
this.colorResolvedConflict = colorResolvedConflict;
this.colorOtherConflict = colorOtherConflict;
insertEmptyLines(true);
setDiffHighlight(true);
copyToResult();
panel.setNumConflicts(diffs.length);
panel.addControlActionListener(this);
showCurrentLine();
this.resultSource = result;
}
private void insertEmptyLines(boolean updateActionLines) {
int n = diffs.length;
for(int i = 0; i < n; i++) {
Difference action = diffs[i];
int n1 = action.getFirstStart() + diffShifts[i][0];
int n2 = action.getFirstEnd() + diffShifts[i][0];
int n3 = action.getSecondStart() + diffShifts[i][1];
int n4 = action.getSecondEnd() + diffShifts[i][1];
if (updateActionLines && i < n - 1) {
diffShifts[i + 1][0] = diffShifts[i][0];
diffShifts[i + 1][1] = diffShifts[i][1];
}
switch (action.getType()) {
case Difference.DELETE:
panel.addEmptyLines2(n3, n2 - n1 + 1);
if (updateActionLines && i < n - 1) {
diffShifts[i+1][1] += n2 - n1 + 1;
}
break;
case Difference.ADD:
panel.addEmptyLines1(n1, n4 - n3 + 1);
if (updateActionLines && i < n - 1) {
diffShifts[i+1][0] += n4 - n3 + 1;
}
break;
case Difference.CHANGE:
int r1 = n2 - n1;
int r2 = n4 - n3;
if (r1 < r2) {
panel.addEmptyLines1(n2, r2 - r1);
if (updateActionLines && i < n - 1) {
diffShifts[i+1][0] += r2 - r1;
}
} else if (r1 > r2) {
panel.addEmptyLines2(n4, r1 - r2);
if (updateActionLines && i < n - 1) {
diffShifts[i+1][1] += r1 - r2;
}
}
break;
}
}
}
private void setDiffHighlight(boolean set) {
int n = diffs.length;
//D.deb("Num Actions = "+n); // NOI18N
for(int i = 0; i < n; i++) {
Difference action = diffs[i];
int n1 = action.getFirstStart() + diffShifts[i][0];
int n2 = action.getFirstEnd() + diffShifts[i][0];
int n3 = action.getSecondStart() + diffShifts[i][1];
int n4 = action.getSecondEnd() + diffShifts[i][1];
//D.deb("Action: "+action.getAction()+": ("+n1+","+n2+","+n3+","+n4+")"); // NOI18N
switch (action.getType()) {
case Difference.DELETE:
if (set) panel.highlightRegion1(n1, n2, colorUnresolvedConflict);
else panel.highlightRegion1(n1, n2, java.awt.Color.white);
break;
case Difference.ADD:
if (set) panel.highlightRegion2(n3, n4, colorUnresolvedConflict);
else panel.highlightRegion2(n3, n4, java.awt.Color.white);
break;
case Difference.CHANGE:
if (set) {
panel.highlightRegion1(n1, n2, colorUnresolvedConflict);
panel.highlightRegion2(n3, n4, colorUnresolvedConflict);
} else {
panel.highlightRegion1(n1, n2, java.awt.Color.white);
panel.highlightRegion2(n3, n4, java.awt.Color.white);
}
break;
}
}
}
private void copyToResult() {
int n = diffs.length;
int line1 = 1;
int line3 = 1;
for(int i = 0; i < n; i++) {
Difference action = diffs[i];
int n1 = action.getFirstStart() + diffShifts[i][0];
int n2 = action.getFirstEnd() + diffShifts[i][0];
int n3 = action.getSecondStart() + diffShifts[i][1];
int n4 = action.getSecondEnd() + diffShifts[i][1];
int endcopy = (action.getType() != Difference.ADD) ? (n1 - 1) : n1;
//System.out.println("diff = "+n1+", "+n2+", "+n3+", "+n4+", endcopy = "+endcopy+((endcopy >= line1) ? "; copy("+line1+", "+endcopy+", "+line3+")" : ""));
if (endcopy >= line1) {
panel.copySource1ToResult(line1, endcopy, line3);
line3 += endcopy + 1 - line1;
}
int length = Math.max(n2 - n1, n4 - n3);
//System.out.println(" length = "+length+", addEmptyLines3("+line3+", "+(length + 1)+")");
panel.addEmptyLines3(line3, length + 1);
panel.highlightRegion3(line3, line3 + length, colorUnresolvedConflict);
resultDiffLocations[i] = line3;
line3 += length + 1;
line1 = Math.max(n2, n4) + 1;
}
//System.out.println("copy("+line1+", -1, "+line3+")");
panel.copySource1ToResult(line1, -1, line3);
}
private void showCurrentLine() {
Difference diff = diffs[currentDiffLine];
int line = diff.getFirstStart() + diffShifts[currentDiffLine][0];
if (diff.getType() == Difference.ADD) line++;
int lf1 = diff.getFirstEnd() - diff.getFirstStart() + 1;
int lf2 = diff.getSecondEnd() - diff.getSecondStart() + 1;
int length = Math.max(lf1, lf2);
panel.setCurrentLine(line, length, currentDiffLine,
resultDiffLocations[currentDiffLine]);
}
/**
* Resolve the merge conflict with left or right part.
* This will reduce the number of conflicts by one.
* @param right If true, use the right part, left otherwise
* @param conflNum The number of conflict.
*/
private void doResolveConflict(boolean right, int conflNum) {
Difference diff = diffs[conflNum];
int[] shifts = diffShifts[conflNum];
int line1, line2, line3, line4;
if (diff.getType() == Difference.ADD) {
line1 = diff.getFirstStart() + shifts[0] + 1;
line2 = line1 - 1;
} else {
line1 = diff.getFirstStart() + shifts[0];
line2 = diff.getFirstEnd() + shifts[0];
}
if (diff.getType() == Difference.DELETE) {
line3 = diff.getSecondStart() + shifts[1] + 1;
line4 = line3 - 1;
} else {
line3 = diff.getSecondStart() + shifts[1];
line4 = diff.getSecondEnd() + shifts[1];
}
//System.out.println(" diff lines = "+line1+", "+line2+", "+line3+", "+line4);
int rlength; // The length of the area before the conflict is resolved
if (resolvedConflicts.contains(diff)) {
rlength = (right) ? (line2 - line1) : (line4 - line3);
} else {
rlength = Math.max(line2 - line1, line4 - line3);
}
int shift;
if (right) {
panel.replaceSource2InResult(line3, Math.max(line4, 0), // Correction for possibly negative value
resultDiffLocations[conflNum],
resultDiffLocations[conflNum] + rlength);
shift = rlength - (line4 - line3);
panel.highlightRegion1(line1, Math.max(line2, 0), colorOtherConflict);
panel.highlightRegion2(line3, Math.max(line4, 0), colorResolvedConflict);
} else {
panel.replaceSource1InResult(line1, Math.max(line2, 0), // Correction for possibly negative value
resultDiffLocations[conflNum],
resultDiffLocations[conflNum] + rlength);
shift = rlength - (line2 - line1);
panel.highlightRegion1(line1, Math.max(line2, 0), colorResolvedConflict);
panel.highlightRegion2(line3, Math.max(line4, 0), colorOtherConflict);
}
if (right && (line4 >= line3) || !right && (line2 >= line1)) {
panel.highlightRegion3(resultDiffLocations[conflNum],
resultDiffLocations[conflNum] + rlength - shift,
colorResolvedConflict);
} else {
panel.unhighlightRegion3(resultDiffLocations[conflNum],
resultDiffLocations[conflNum]);
}
for (int i = conflNum + 1; i < diffs.length; i++) {
resultDiffLocations[i] -= shift;
}
resolvedConflicts.add(diff);
panel.setNeedsSaveState(true);
}
public void actionPerformed(ActionEvent actionEvent) {
final String actionCommand = actionEvent.getActionCommand();
org.openide.util.RequestProcessor.getDefault().post(new Runnable() {
public void run() {
if (MergePanel.ACTION_FIRST_CONFLICT.equals(actionCommand)) {
currentDiffLine = 0;
showCurrentLine();
} else if (MergePanel.ACTION_LAST_CONFLICT.equals(actionCommand)) {
currentDiffLine = diffs.length - 1;
showCurrentLine();
} else if (MergePanel.ACTION_PREVIOUS_CONFLICT.equals(actionCommand)) {
currentDiffLine--;
if (currentDiffLine < 0) currentDiffLine = diffs.length - 1;
showCurrentLine();
} else if (MergePanel.ACTION_NEXT_CONFLICT.equals(actionCommand)) {
currentDiffLine++;
if (currentDiffLine >= diffs.length) currentDiffLine = 0;
showCurrentLine();
} else if (MergePanel.ACTION_ACCEPT_RIGHT.equals(actionCommand)) {
doResolveConflict(true, currentDiffLine);
} else if (MergePanel.ACTION_ACCEPT_LEFT.equals(actionCommand)) {
doResolveConflict(false, currentDiffLine);
}
}
});
}
public void vetoableChange(PropertyChangeEvent propertyChangeEvent) throws PropertyVetoException {
if (MergeDialogComponent.PROP_PANEL_SAVE.equals(propertyChangeEvent.getPropertyName())) {
MergePanel panel = (MergePanel) propertyChangeEvent.getNewValue();
if (this.panel == panel) {
ArrayList unresolvedConflicts = new ArrayList();//java.util.Arrays.asList(diffs));
int diffLocationShift = 0;
for (int i = 0; i < diffs.length; i++) {
if (!resolvedConflicts.contains(diffs[i])) {
int diffLocation = resultDiffLocations[i] - diffLocationShift;
Difference conflict = new Difference(diffs[i].getType(),
diffLocation,
diffLocation + diffs[i].getFirstEnd() - diffs[i].getFirstStart(),
diffLocation,
diffLocation + diffs[i].getSecondEnd() - diffs[i].getSecondStart(),
diffs[i].getFirstText(),
diffs[i].getSecondText());
unresolvedConflicts.add(conflict);
diffLocationShift += Math.max(diffs[i].getFirstEnd() - diffs[i].getFirstStart() + 1,
diffs[i].getSecondEnd() - diffs[i].getSecondStart() + 1);
}
}
try {
panel.writeResult(resultSource.createWriter((Difference[]) unresolvedConflicts.toArray(
new Difference[unresolvedConflicts.size()])));
panel.setNeedsSaveState(false);
} catch (IOException ioex) {
throw new PropertyVetoException(NbBundle.getMessage(MergeControl.class,
"MergeControl.failedToSave",
ioex.getLocalizedMessage()),
propertyChangeEvent);
}
}
}
if (MergeDialogComponent.PROP_PANEL_CLOSING.equals(propertyChangeEvent.getPropertyName())) {
MergePanel panel = (MergePanel) propertyChangeEvent.getNewValue();
if (this.panel == panel) {
resultSource.close();
}
}
if (MergeDialogComponent.PROP_ALL_CLOSED.equals(propertyChangeEvent.getPropertyName()) ||
MergeDialogComponent.PROP_ALL_CANCELLED.equals(propertyChangeEvent.getPropertyName())) {
resultSource.close();
}
}
}
|
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.