1 19 20 package org.netbeans.modules.diff.builtin.visualizer; 21 22 import java.util.*; 23 import java.io.*; 24 import javax.swing.*; 25 import javax.swing.text.*; 26 import java.awt.BorderLayout ; 27 28 import org.openide.util.HelpCtx; 29 import org.openide.windows.*; 30 31 import org.netbeans.api.diff.Difference; 32 import org.netbeans.modules.diff.builtin.DiffPresenter; 33 34 37 43 public class DiffComponent extends org.openide.windows.TopComponent { 44 45 public static final java.awt.Color COLOR_MISSING = new java.awt.Color (255, 160, 180); 46 public static final java.awt.Color COLOR_ADDED = new java.awt.Color (180, 255, 180); 47 public static final java.awt.Color COLOR_CHANGED = new java.awt.Color (160, 200, 255); 48 49 private Difference[] diffs = null; 51 52 private int[][] diffShifts; 53 private DiffPanel diffPanel = null; 54 55 private java.awt.Color colorMissing = COLOR_MISSING; 56 private java.awt.Color colorAdded = COLOR_ADDED; 57 private java.awt.Color colorChanged = COLOR_CHANGED; 58 59 private int currentDiffLine = -1; 61 62 65 private boolean diffSetSuccess = true; 66 67 static final long serialVersionUID =3683458237532937983L; 68 69 72 public DiffComponent() { 73 putClientProperty("PersistenceType", "Never"); 74 } 75 76 77 public DiffComponent(final Difference[] diffs, final String mainTitle, final String mimeType, 78 final String sourceName1, final String sourceName2, 79 final String title1, final String title2, 80 final Reader r1, final Reader r2) { 81 this(diffs, mainTitle, mimeType, sourceName1, sourceName2, title1, title2, 82 r1, r2, null); 83 } 84 85 86 public DiffComponent(final Difference[] diffs, final String mainTitle, final String mimeType, 87 final String sourceName1, final String sourceName2, 88 final String title1, final String title2, 89 final Reader r1, final Reader r2, java.awt.Color [] colors) { 90 this.diffs = diffs; 91 diffShifts = new int[diffs.length][2]; 92 setLayout(new BorderLayout ()); 93 diffPanel = new DiffPanel(); 94 putClientProperty(DiffPresenter.PROP_TOOLBAR, diffPanel.getClientProperty(DiffPresenter.PROP_TOOLBAR)); 95 diffPanel.addPrevLineButtonListener(new java.awt.event.ActionListener () { 96 public void actionPerformed(java.awt.event.ActionEvent evt) { 97 if (diffs.length == 0) return ; 98 currentDiffLine--; 99 if (currentDiffLine < 0) currentDiffLine = diffs.length - 1; 100 showCurrentLine(); 101 } 102 }); 103 diffPanel.addNextLineButtonListener(new java.awt.event.ActionListener () { 104 public void actionPerformed(java.awt.event.ActionEvent evt) { 105 if (diffs.length == 0) return ; 106 currentDiffLine++; 107 if (currentDiffLine >= diffs.length) currentDiffLine = 0; 108 showCurrentLine(); 109 } 110 }); 111 add(diffPanel, BorderLayout.CENTER); 112 113 if (colors != null && colors.length >= 3) { 114 colorMissing = colors[0]; 115 colorAdded = colors[1]; 116 colorChanged = colors[2]; 117 } 118 if (mainTitle == null) { 121 setName(org.openide.util.NbBundle.getBundle(DiffComponent.class).getString("DiffComponent.title")); 122 } else { 123 setName(mainTitle); 124 } 125 setIcon(org.openide.util.Utilities.loadImage("org/netbeans/modules/diff/diffSettingsIcon.gif", true)); 126 initContent(mimeType, sourceName1, sourceName2, title1, title2, r1, r2); 127 putClientProperty("PersistenceType", "Never"); 129 } 130 131 public HelpCtx getHelpCtx() { 132 return new HelpCtx(DiffComponent.class); 133 } 134 135 136 137 private void showCurrentLine() { 138 if (currentDiffLine >= diffs.length) return; 139 Difference diff = diffs[currentDiffLine]; 140 int line = diff.getFirstStart() + diffShifts[currentDiffLine][0]; 141 if (diff.getType() == Difference.ADD) line++; 142 int lf1 = diff.getFirstEnd() - diff.getFirstStart() + 1; 143 int lf2 = diff.getSecondEnd() - diff.getSecondStart() + 1; 144 int length = Math.max(lf1, lf2); 145 diffPanel.setCurrentLine(line, length); 146 } 147 148 private void initContent(String mimeType, String sourceName1, String sourceName2, 149 String title1, String title2, Reader r1, Reader r2) { 150 setMimeType1(mimeType); 151 setMimeType2(mimeType); 152 try { 153 setSource1(r1); 154 setSource2(r2); 155 } catch (IOException ioex) { 156 org.openide.ErrorManager.getDefault().notify(ioex); 157 } 158 setSource1Title(title1); 159 setSource2Title(title2); 160 insertEmptyLines(true); 161 setDiffHighlight(true); 162 insertEmptyLinesNotReported(); 163 } 164 165 @Deprecated 166 public void open(Workspace workspace) { 167 super.open(workspace); 168 diffPanel.open(); 169 if (currentDiffLine < 0) { 170 currentDiffLine = 0; 171 showCurrentLine(); 172 } 173 } 174 175 178 @Deprecated 179 public void requestFocus() { 180 super.requestFocus(); 181 diffPanel.requestFocus(); 182 } 183 184 187 @Deprecated 188 public boolean requestFocusInWindow() { 189 super.requestFocusInWindow(); 190 return diffPanel.requestFocusInWindow(); 191 } 192 193 public void addNotify() { 194 super.addNotify(); 195 if (currentDiffLine < 0) { 196 javax.swing.SwingUtilities.invokeLater(new Runnable () { 197 public void run() { 198 diffPanel.open(); 199 javax.swing.SwingUtilities.invokeLater(new Runnable () { 200 public void run() { 201 java.awt.Toolkit.getDefaultToolkit().sync(); 202 javax.swing.SwingUtilities.invokeLater(new Runnable () { 203 public void run() { 204 if (currentDiffLine < 0) { 205 currentDiffLine = 0; 206 showCurrentLine(); 207 } 208 } 209 }); 210 } 211 }); 212 } 213 }); 214 } 215 } 216 217 221 @Deprecated 222 public boolean canClose(Workspace workspace, boolean last) { 223 boolean can = super.canClose(workspace, last); 224 if (last && can) { 225 exitForm(null); 226 } 227 return can; 228 } 229 236 237 public void setSource1(Reader r) throws IOException { 238 diffPanel.setSource1(r); 239 } 240 241 public void setSource2(Reader r) throws IOException { 242 diffPanel.setSource2(r); 243 } 244 245 public void setSource1Title(String title) { 246 diffPanel.setSource1Title(title); 247 } 248 249 public void setSource2Title(String title) { 250 diffPanel.setSource2Title(title); 251 } 252 253 public void setMimeType1(String mime) { 254 diffPanel.setMimeType1(mime); 255 } 256 257 public void setMimeType2(String mime) { 258 diffPanel.setMimeType2(mime); 259 } 260 261 public void setDocument1(Document doc) { 262 diffPanel.setDocument1(doc); 263 } 264 265 public void setDocument2(Document doc) { 266 diffPanel.setDocument2(doc); 267 } 268 269 public void unhighlightAll() { 270 diffPanel.unhighlightAll(); 271 } 272 273 public void highlightRegion1(int line1, int line2, java.awt.Color color) { 274 diffPanel.highlightRegion1(line1, line2, color); 276 } 277 278 public void highlightRegion2(int line1, int line2, java.awt.Color color) { 279 diffPanel.highlightRegion2(line1, line2, color); 281 } 282 283 public void addEmptyLines1(int line, int numLines) { 284 diffPanel.addEmptyLines1(line, numLines); 285 } 286 287 public void addEmptyLines2(int line, int numLines) { 288 diffPanel.addEmptyLines2(line, numLines); 289 } 290 291 public void writeExternal(ObjectOutput out) throws IOException { 292 super.writeExternal(out); 293 out.writeObject(diffs); 295 302 } 303 304 private void insertEmptyLines(boolean updateActionLines) { 305 int n = diffs.length; 306 for(int i = 0; i < n; i++) { 310 Difference action = diffs[i]; 311 int n1 = action.getFirstStart() + diffShifts[i][0]; 312 int n2 = action.getFirstEnd() + diffShifts[i][0]; 313 int n3 = action.getSecondStart() + diffShifts[i][1]; 314 int n4 = action.getSecondEnd() + diffShifts[i][1]; 315 if (updateActionLines && i < n - 1) { 318 diffShifts[i + 1][0] = diffShifts[i][0]; 319 diffShifts[i + 1][1] = diffShifts[i][1]; 320 } 321 switch (action.getType()) { 322 case Difference.DELETE: 323 addEmptyLines2(n3, n2 - n1 + 1); 324 if (updateActionLines && i < n - 1) { 325 diffShifts[i+1][1] += n2 - n1 + 1; 326 } 327 break; 329 case Difference.ADD: 330 addEmptyLines1(n1, n4 - n3 + 1); 331 if (updateActionLines && i < n - 1) { 332 diffShifts[i+1][0] += n4 - n3 + 1; 333 } 334 break; 336 case Difference.CHANGE: 337 int r1 = n2 - n1; 338 int r2 = n4 - n3; 339 if (r1 < r2) { 340 addEmptyLines1(n2, r2 - r1); 341 if (updateActionLines && i < n - 1) { 342 diffShifts[i+1][0] += r2 - r1; 343 } 344 } else if (r1 > r2) { 346 addEmptyLines2(n4, r1 - r2); 347 if (updateActionLines && i < n - 1) { 348 diffShifts[i+1][1] += r1 - r2; 349 } 350 } 352 break; 353 } 354 } 355 } 356 357 private void setDiffHighlight(boolean set) { 358 int n = diffs.length; 359 for(int i = 0; i < n; i++) { 361 Difference action = diffs[i]; 362 int n1 = action.getFirstStart() + diffShifts[i][0]; 363 int n2 = action.getFirstEnd() + diffShifts[i][0]; 364 int n3 = action.getSecondStart() + diffShifts[i][1]; 365 int n4 = action.getSecondEnd() + diffShifts[i][1]; 366 switch (action.getType()) { 368 case Difference.DELETE: 369 if (set) highlightRegion1(n1, n2, colorMissing); 370 else highlightRegion1(n1, n2, java.awt.Color.white); 371 break; 372 case Difference.ADD: 373 if (set) highlightRegion2(n3, n4, colorAdded); 374 else highlightRegion2(n3, n4, java.awt.Color.white); 375 break; 376 case Difference.CHANGE: 377 if (set) { 378 highlightRegion1(n1, n2, colorChanged); 379 highlightRegion2(n3, n4, colorChanged); 380 } else { 381 highlightRegion1(n1, n2, java.awt.Color.white); 382 highlightRegion2(n3, n4, java.awt.Color.white); 383 } 384 break; 385 } 386 } 387 } 388 389 398 private static String readLine(int[] begin, int[] end, String text) { 399 int n = text.length(); 400 for (int i = begin[0]; i < n; i++) { 401 char c = text.charAt(i); 402 if (c == '\n' || c == '\r') { 403 end[0] = i; 404 break; 405 } 406 } 407 if (end[0] < begin[0]) end[0] = n; 408 String line = text.substring(begin[0], end[0]); 409 begin[0] = end[0] + 1; 410 if (begin[0] < n && text.charAt(end[0]) == '\r' && text.charAt(begin[0]) == '\n') begin[0]++; 411 return line; 412 } 413 414 420 private static int findDiffForLine(int lineNumber, int diffIndex, Difference[] diffs, int[][] diffShifts) { 421 while (diffIndex < diffs.length) { 422 if ((diffs[diffIndex].getFirstEnd() + diffShifts[diffIndex][0]) >= lineNumber || 423 (diffs[diffIndex].getSecondEnd() + diffShifts[diffIndex][1]) >= lineNumber) break; 424 diffIndex++; 425 } 426 return diffIndex; 427 } 428 429 436 private static boolean isLineInDiff(int lineNumber, Difference diff, int[] diffShifts) { 437 int l1 = diff.getFirstStart() + diffShifts[0]; 438 int l2 = diff.getFirstEnd() + diffShifts[0]; 439 int l3 = diff.getSecondStart() + diffShifts[1]; 440 int l4 = diff.getSecondEnd() + diffShifts[1]; 441 return (l1 <= lineNumber && ((l2 >= l1) ? (l2 >= lineNumber) : false)) || 442 (l3 <= lineNumber && ((l4 >= l3) ? (l4 >= lineNumber) : false)); 443 } 444 445 private static int numEmptyLines(int beginLine, String text, int endLine) { 446 if (endLine >= 0 && endLine <= beginLine) return 0; 447 int numLines = 0; 448 int[] begin = { beginLine }; 449 int[] end = { 0 }; 450 do { 451 String line = readLine(begin, end, text); 452 if (line.trim().length() > 0) break; 453 numLines++; 454 } while ((endLine < 0 || beginLine + numLines < endLine) && begin[0] < text.length()); 455 return numLines; 456 } 457 458 474 private void insertEmptyLinesNotReported() { 475 String docText1 = diffPanel.getDocumentText1(); 476 String docText2 = diffPanel.getDocumentText2(); 477 int[] begin1 = { 0 }; 478 int[] end1 = { -1 }; 479 int[] begin2 = { 0 }; 480 int[] end2 = { -1 }; 481 int n1 = docText1.length(); 482 int n2 = docText2.length(); 483 int lineNumber = 1; 484 int diffIndex = 0; 485 do { 486 int lastBegin1 = begin1[0]; 487 int lastBegin2 = begin2[0]; 488 String line1 = readLine(begin1, end1, docText1); 489 String line2 = readLine(begin2, end2, docText2); 490 if (line1.length() == 0 && line2.length() > 0) { 491 diffIndex = findDiffForLine(lineNumber, diffIndex, diffs, diffShifts); 493 if (diffIndex >= diffs.length || !isLineInDiff(lineNumber, diffs[diffIndex], diffShifts[diffIndex])) { 494 boolean addMissingLine; 495 if (line2.trim().length() == 0) { 496 int emptyLines1 = numEmptyLines(begin1[0], docText1, (diffIndex < diffs.length) ? diffs[diffIndex].getFirstStart() : -1); 497 int emptyLines2 = numEmptyLines(begin2[0], docText2, (diffIndex < diffs.length) ? diffs[diffIndex].getSecondStart() : -1); 498 addMissingLine = emptyLines1 > emptyLines2; 499 } else { 501 addMissingLine = true; 502 } 503 if (addMissingLine) { 504 addEmptyLines2(lineNumber - 1, 1); 505 shiftDiffs(false, lineNumber); 507 begin2[0] = lastBegin2; 508 end2[0] = lastBegin2 - 1; 509 } 510 } 511 } else if (line2.length() == 0 && line1.length() > 0) { 512 diffIndex = findDiffForLine(lineNumber, diffIndex, diffs, diffShifts); 514 if (diffIndex >= diffs.length || !isLineInDiff(lineNumber, diffs[diffIndex], diffShifts[diffIndex])) { 515 boolean addMissingLine; 516 if (line1.trim().length() == 0) { 517 int emptyLines1 = numEmptyLines(begin1[0], docText1, (diffIndex < diffs.length) ? diffs[diffIndex].getFirstStart() : -1); 518 int emptyLines2 = numEmptyLines(begin2[0], docText2, (diffIndex < diffs.length) ? diffs[diffIndex].getSecondStart() : -1); 519 addMissingLine = emptyLines2 > emptyLines1; 520 } else { 522 addMissingLine = true; 523 } 524 if (addMissingLine) { 525 addEmptyLines1(lineNumber - 1, 1); 526 shiftDiffs(true, lineNumber); 528 begin1[0] = lastBegin1; 529 end1[0] = lastBegin1 - 1; 530 } 531 } 532 } 533 lineNumber++; 534 } while (begin1[0] < n1 && begin2[0] < n2); 535 } 536 537 542 private void shiftDiffs(boolean inFirstDoc, int fromLine) { 543 int n = diffs.length; 544 for(int i = 0; i < n; i++) { 545 Difference action = diffs[i]; 546 if (inFirstDoc) { 547 if (action.getFirstStart() + diffShifts[i][0] >= fromLine) { 548 diffShifts[i][0]++; 549 } 550 } else { 551 if (action.getSecondStart() + diffShifts[i][1] >= fromLine) { 552 diffShifts[i][1]++; 553 } 554 } 555 } 556 } 557 558 public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { 559 super.readExternal(in); 560 Object obj = in.readObject(); 561 diffs = (Difference[]) obj; 562 diffPanel = new DiffPanel(); 563 } 565 566 private Object readResolve() throws ObjectStreamException { 567 if (this.diffSetSuccess) return this; 568 else return null; 569 } 570 571 574 protected Object writeReplace () throws java.io.ObjectStreamException { 575 exitForm(null); 576 return null; 577 } 578 579 580 private void exitForm(java.awt.event.WindowEvent evt) { 581 SwingUtilities.invokeLater(new Runnable () { 582 public void run() { 583 diffPanel = null; 584 diffs = null; 585 removeAll(); 586 } 587 }); 588 595 604 605 } 606 607 } 608 | Popular Tags |