package processor;
public class Data {
private String content;
private int[] formatArray;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public int[] getFormatArray() {
return formatArray;
}
private void setFormatArray(int[] formatArray) {
this.formatArray = formatArray;
}
public void setFormat(int index, int format) {
formatArray[index] = format;
}
public int getFormat(int index) {
return formatArray[index];
}
public static Data create(String contentString) {
Data data = new Data();
data.setContent(contentString);
data.setFormatArray(new int[contentString.length()]);
return data;
}
}
package processor;
public class DiffProcessor {
private static DiffProcessor instance;
public static DiffProcessor getInstance() {
if (instance == null) {
instance = new DiffProcessor();
}
return instance;
}
public void process(Data data1, Data data2) {
recursiveProcess(data1, 0, data1.getContent().length() - 1, data2, 0, data2.getContent().length() - 1);
}
private void copyArrayValue(int[] array1, int[] array2) {
if (array1.length == array2.length) {
for(int i = 0; i < array1.length; i++) {
array1[i] = array2[i];
}
} else {
return;
}
}
private int[] LCS(String str1, int str1BeginIndex, int str1EndIndex, String str2, int str2BeginIndex, int str2EndIndex) {
int arrayX = str1EndIndex - str1BeginIndex + 1;
int arrayY = str2EndIndex - str2BeginIndex + 1;
int[][] LCSArray = new int[2][arrayY];
int maxValue = 0;
int xMax = 0;
int yMax = 0;
for(int x = 0; x < arrayX; x++) {
for(int y = 0; y < arrayY; y++) {
if (str1.charAt(x + str1BeginIndex) == str2.charAt(y + str2BeginIndex)) {
if (x > 0 && y > 0) {
LCSArray[1][y] = LCSArray[0][y - 1] + 1;
if (LCSArray[1][y] > maxValue) {
maxValue = LCSArray[1][y];
xMax = x;
yMax = y;
}
} else {
LCSArray[1][y] = 1;
}
} else {
LCSArray[1][y] = 0;
}
}
copyArrayValue(LCSArray[0], LCSArray[1]);
}
return new int[] { maxValue, xMax, yMax };
}
private void recursiveProcess(Data data1, int str1BeginIndex, int str1EndIndex, Data data2, int str2BeginIndex, int str2EndIndex) {
int[] LCSResult = LCS(data1.getContent(), str1BeginIndex, str1EndIndex, data2.getContent(), str2BeginIndex, str2EndIndex);
int maxValue = LCSResult[0];
int xMax = LCSResult[1];
int yMax = LCSResult[2];
if (maxValue != 0) {
int xSamePartStartIndex = str1BeginIndex + xMax - maxValue + 1;
int xSamePartEndIndex = xSamePartStartIndex + maxValue - 1;
int ySamePartStartIndex = str2BeginIndex + yMax - maxValue + 1;
int ySamePartEndIndex = ySamePartStartIndex + maxValue - 1;
for(int i = xSamePartStartIndex; i <= xSamePartEndIndex; i++) {
data1.setFormat(i, 0);
}
for(int i = ySamePartStartIndex; i <= ySamePartEndIndex; i++) {
data2.setFormat(i, 0);
}
if (xSamePartStartIndex - str1BeginIndex <= 0) {
for(int i = str2BeginIndex; i < ySamePartStartIndex; i++) {
data2.setFormat(i, 1);
}
} else if (ySamePartStartIndex - str2BeginIndex <= 0) {
for(int i = str1BeginIndex; i < xSamePartStartIndex; i++) {
data1.setFormat(i, 1);
}
} else {
recursiveProcess(data1, str1BeginIndex, xSamePartStartIndex - 1, data2, str2BeginIndex, ySamePartStartIndex - 1);
}
if (str1EndIndex - xSamePartEndIndex <= 0) {
for(int i = ySamePartEndIndex + 1; i <= str2EndIndex; i++) {
data2.setFormat(i, 1);
}
} else if (str2EndIndex - ySamePartEndIndex <= 0) {
for(int i = xSamePartEndIndex + 1; i <= str1EndIndex; i++) {
data1.setFormat(i, 1);
}
} else {
recursiveProcess(data1, xSamePartEndIndex + 1, str1EndIndex, data2, ySamePartEndIndex + 1, str2EndIndex);
}
} else {
for(int i = str1BeginIndex; i <= str1EndIndex; i++) {
data1.setFormat(i, 1);
}
for(int i = str2BeginIndex; i <= str2EndIndex; i++) {
data2.setFormat(i, 1);
}
return;
}
}
}
package ui;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.WindowConstants;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import processor.Data;
import processor.DiffProcessor;
public class DiffToolFrame extends JFrame {
private MyJTextPane jTextPaneA;
private MyJTextPane jTextPaneB;
public DiffToolFrame() {
VierMenuBar menuTest = new VierMenuBar();
CenterPanel centerPanel = new CenterPanel();
BottomPanel bottomPanel = new BottomPanel();
this.setJMenuBar(menuTest);
Container c = this.getContentPane();
c.add(centerPanel, BorderLayout.CENTER);
c.add(bottomPanel, BorderLayout.SOUTH);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setSize(700, 500);
setTitle("Diff Tool v1.0");
setLocation(200, 150);
setVisible(true);
this.addWindowListener(new WindowAdapter() {
public void WindowClosing(WindowEvent e) {
dispose();
System.exit(0);
}
});
}
class VierMenuBar extends JMenuBar {
private JDialog aboutDialog;
public VierMenuBar() {
JMenu fileMenu = new JMenu("File");
JMenuItem exitMenuItem = new JMenuItem("Exit", KeyEvent.VK_E);
JMenuItem aboutMenuItem = new JMenuItem("About", KeyEvent.VK_A);
this.add(fileMenu);
fileMenu.add(exitMenuItem);
fileMenu.add(aboutMenuItem);
// about dialog
Icon icon = new ImageIcon("smile.gif");
JLabel aboutLabel = new JLabel("<html><b><font size=5>" + "<center>Diff Tool" + "<br>v1.0", icon, JLabel.CENTER);
aboutDialog = new JDialog();
aboutDialog.getContentPane().add(aboutLabel, BorderLayout.CENTER);
aboutDialog.setSize(450, 225);
aboutDialog.setLocation(300, 300);
aboutDialog.setTitle("About");
aboutDialog.addWindowListener(new WindowAdapter() {
public void WindowClosing(WindowEvent e) {
dispose();
}
});
exitMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dispose();
System.exit(0);
}
});
aboutMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
aboutDialog.setVisible(true);
}
});
}
}
class CenterPanel extends JPanel {
public CenterPanel() {
jTextPaneA = new MyJTextPane();
jTextPaneB = new MyJTextPane();
JScrollPane jScrollPane1 = createJScrollPane(jTextPaneA);
JScrollPane jScrollPane2 = createJScrollPane(jTextPaneB);
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, jScrollPane1, jScrollPane2);
this.setLayout(new BorderLayout());
this.add(splitPane, BorderLayout.CENTER);
this.setEnabled(true);
}
private JScrollPane createJScrollPane(MyJTextPane jTextPane) {
jTextPane.setDocument(new DefaultStyledDocument());
new DropTarget(jTextPane, DnDConstants.ACTION_COPY_OR_MOVE, jTextPane);
JScrollPane jScrollPane = new JScrollPane();
jScrollPane.setViewportView(jTextPane);
return jScrollPane;
}
}
class BottomPanel extends JPanel {
public BottomPanel() {
JButton compareButton = new JButton("Compare");
compareButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
DefaultStyledDocument docA = (DefaultStyledDocument) jTextPaneA.getDocument();
DefaultStyledDocument docB = (DefaultStyledDocument) jTextPaneB.getDocument();
try {
Data data1 = Data.create(docA.getText(0, docA.getLength()));
Data data2 = Data.create(docB.getText(0, docB.getLength()));
DiffProcessor dp = DiffProcessor.getInstance();
dp.process(data1, data2);
MutableAttributeSet diffAttr = new SimpleAttributeSet();
MutableAttributeSet defaultAttr = new SimpleAttributeSet();
StyleConstants.setForeground(diffAttr, Color.red);
StyleConstants.setForeground(defaultAttr, Color.black);
// set jTextPaneA
for(int i = 0; i < data1.getFormatArray().length; i++) {
if (data1.getFormat(i) == 1) {
docA.setCharacterAttributes(i, 1, diffAttr, true);
} else {
docA.setCharacterAttributes(i, 1, defaultAttr, true);
}
}
// set jTextPaneB
for(int i = 0; i < data2.getFormatArray().length; i++) {
if (data2.getFormat(i) == 1) {
docB.setCharacterAttributes(i, 1, diffAttr, true);
} else {
docB.setCharacterAttributes(i, 1, defaultAttr, true);
}
}
} catch (BadLocationException e1) {
e1.printStackTrace();
}
}
});
this.setLayout(new BorderLayout());
this.add(compareButton, BorderLayout.CENTER);
}
}
public static void main(String args[]) {
new DiffToolFrame();
}
}
package ui;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Document;
import util.MyUtil;
public class MyJTextPane extends JTextPane implements DropTargetListener {
public MyJTextPane() {
super();
}
@Override
public void dragEnter(DropTargetDragEvent dtde) {
}
@Override
public void dragExit(DropTargetEvent dte) {
}
@Override
public void dragOver(DropTargetDragEvent dtde) {
}
@Override
public void drop(DropTargetDropEvent dtde) {
try {
// clean JTextPane
Document doc = this.getDocument();
try {
doc.remove(0, doc.getLength());
} catch (BadLocationException e1) {
e1.printStackTrace();
}
Transferable tr = dtde.getTransferable();
if (dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
List list = (List) (dtde.getTransferable().getTransferData(DataFlavor.javaFileListFlavor));
Iterator iterator = list.iterator();
while(iterator.hasNext()) {
File f = (File) iterator.next();
try {
doc.insertString(0, MyUtil.readFile(f.getAbsolutePath()), null);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
dtde.dropComplete(true);
// this.updateUI();
} else {
dtde.rejectDrop();
}
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (UnsupportedFlavorException ufe) {
ufe.printStackTrace();
}
}
@Override
public void dropActionChanged(DropTargetDragEvent dtde) {
}
}
package util;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class MyUtil {
public static String readFile(String filePath) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(filePath));
StringBuilder sb = new StringBuilder();
String line;
while((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
return sb.toString();
}
public static void main(String[] args) {
try {
System.out.println(readFile(""));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}