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(); } } }