1 19 20 package org.netbeans.modules.subversion.ui.diff; 21 22 import java.io.*; 23 import org.netbeans.api.diff.*; 24 import org.netbeans.api.diff.Diff; 25 import org.netbeans.api.diff.DiffView; 26 import org.netbeans.api.diff.StreamSource; 27 import org.netbeans.modules.subversion.*; 28 import org.netbeans.modules.subversion.client.*; 29 import org.netbeans.modules.subversion.ui.commit.*; 30 import org.netbeans.modules.subversion.util.*; 31 import org.netbeans.modules.versioning.util.VersioningListener; 32 import org.netbeans.modules.versioning.util.VersioningEvent; 33 import org.netbeans.modules.versioning.util.DelegatingUndoRedo; 34 import org.netbeans.spi.diff.*; 35 import org.openide.util.Lookup; 36 import org.openide.util.NbBundle; 37 import org.openide.util.RequestProcessor; 38 import org.openide.util.Task; 39 import org.openide.util.TaskListener; 40 import org.openide.util.lookup.Lookups; 41 import org.openide.ErrorManager; 42 import org.openide.LifecycleManager; 43 import org.openide.awt.UndoRedo; 44 import org.openide.nodes.Node; 45 import org.openide.nodes.AbstractNode; 46 import org.openide.nodes.Children; 47 import org.openide.windows.TopComponent; 48 import org.openide.windows.WindowManager; 49 import org.openide.filesystems.FileObject; 50 import org.openide.filesystems.FileUtil; 51 52 import javax.swing.*; 53 import javax.swing.plaf.basic.BasicComboBoxRenderer ; 54 import javax.swing.border.CompoundBorder ; 55 import java.io.IOException ; 56 import java.io.File ; 57 import java.util.*; 58 import java.util.List ; 59 import java.awt.event.*; 60 import java.awt.*; 61 import java.awt.image.BufferedImage ; 62 import org.netbeans.modules.subversion.ui.status.StatusAction; 63 import org.netbeans.modules.subversion.ui.update.UpdateAction; 64 import org.netbeans.modules.subversion.ui.actions.ContextAction; 65 66 71 public class DiffMainPanel extends javax.swing.JPanel implements ActionListener, VersioningListener, DiffSetupSource { 72 73 77 private Setup[] setups; 78 79 private final DelegatingUndoRedo delegatingUndoRedo = new DelegatingUndoRedo(); 80 83 private final Context context; 84 85 private int displayStatuses; 86 87 90 private final String contextName; 91 92 private int currentType; 93 private int currentDifferenceIndex; 94 private int currentIndex = -1; 95 96 private RequestProcessor.Task prepareTask; 97 private DiffPrepareTask dpt; 98 99 private AbstractAction nextAction; 100 private AbstractAction prevAction; 101 102 private static final RequestProcessor rp = new RequestProcessor("SVN_DIFF", 1); 105 108 private RequestProcessor.Task refreshTask; 109 110 private JComponent diffView; 111 112 private SvnProgressSupport executeStatusSupport; 113 114 117 public DiffMainPanel(Context context, int initialType, String contextName) { 118 this.context = context; 119 this.contextName = contextName; 120 currentType = initialType; 121 initComponents(); 122 setupComponents(); 123 refreshSetups(); 124 refreshComponents(); 125 refreshTask = rp.create(new RefreshViewTask()); 126 } 127 128 132 public DiffMainPanel(File file, String rev1, String rev2) { 133 context = null; 134 contextName = file.getName(); 135 initComponents(); 136 setupComponents(); 137 localToggle.setVisible(false); 138 remoteToggle.setVisible(false); 139 allToggle.setVisible(false); 140 navigationCombo.setVisible(false); 141 refreshButton.setVisible(false); 142 updateButton.setVisible(false); 143 commitButton.setVisible(false); 144 145 setups = new Setup[] { 147 new Setup(file, rev1, rev2) 148 }; 149 setDiffIndex(0, 0); 150 dpt = new DiffPrepareTask(setups); 151 prepareTask = RequestProcessor.getDefault().post(dpt); 152 } 153 154 157 void componentClosed() { 158 setups = null; 159 if (prepareTask != null) { 160 prepareTask.cancel(); 161 } 162 if(executeStatusSupport!=null) { 163 executeStatusSupport.cancel(); 164 } 165 } 166 167 void requestActive() { 168 if (diffView != null) { 169 diffView.requestFocusInWindow(); 170 } 171 } 172 173 public UndoRedo getUndoRedo() { 174 return delegatingUndoRedo; 175 } 176 177 private static class ColoredComboRenderer extends BasicComboBoxRenderer { 178 179 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { 180 if (isSelected) { 181 value = ((Setup) value).getBaseFile().getName(); 182 } 183 return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 184 } 185 } 186 187 private void setupComponents() { 188 controlsToolbar.putClientProperty("JToolBar.isRollover", Boolean.TRUE); controlsToolbar.setLayout(new DiffMainPanel.ToolbarLayout()); 190 191 navigationCombo.addActionListener(this); 192 navigationCombo.setRenderer(new ColoredComboRenderer()); 193 refreshButton.addActionListener(this); 194 updateButton.addActionListener(this); 195 commitButton.addActionListener(this); 196 localToggle.addActionListener(this); 197 remoteToggle.addActionListener(this); 198 allToggle.addActionListener(this); 199 200 refreshButton.setToolTipText(NbBundle.getMessage(DiffMainPanel.class, "MSG_RefreshDiff_Tooltip")); updateButton.setToolTipText(NbBundle.getMessage(DiffMainPanel.class, "MSG_UpdateDiff_Tooltip", contextName)); commitButton.setToolTipText(NbBundle.getMessage(DiffMainPanel.class, "MSG_CommitDiff_Tooltip", contextName)); ButtonGroup grp = new ButtonGroup(); 204 grp.add(localToggle); 205 grp.add(remoteToggle); 206 grp.add(allToggle); 207 if (currentType == Setup.DIFFTYPE_LOCAL) localToggle.setSelected(true); 208 else if (currentType == Setup.DIFFTYPE_REMOTE) remoteToggle.setSelected(true); 209 else if (currentType == Setup.DIFFTYPE_ALL) allToggle.setSelected(true); 210 211 nextAction = new AbstractAction(null, new javax.swing.ImageIcon (getClass().getResource("/org/netbeans/modules/subversion/resources/icons/diff-next.png"))) { { 213 putValue(Action.SHORT_DESCRIPTION, java.util.ResourceBundle.getBundle("org/netbeans/modules/subversion/ui/diff/Bundle"). getString("CTL_DiffPanel_Next_Tooltip")); } 216 public void actionPerformed(ActionEvent e) { 217 onNextButton(); 218 } 219 }; 220 prevAction = new AbstractAction(null, new javax.swing.ImageIcon (getClass().getResource("/org/netbeans/modules/subversion/resources/icons/diff-prev.png"))) { { 222 putValue(Action.SHORT_DESCRIPTION, java.util.ResourceBundle.getBundle("org/netbeans/modules/subversion/ui/diff/Bundle"). getString("CTL_DiffPanel_Prev_Tooltip")); } 225 public void actionPerformed(ActionEvent e) { 226 onPrevButton(); 227 } 228 }; 229 nextButton.setAction(nextAction); 230 prevButton.setAction(prevAction); 231 } 232 233 private void refreshComponents() { 234 DiffView view = setups != null ? setups[currentIndex].getView() : null; 235 if (view != null) { 236 nextAction.setEnabled(currentIndex < setups.length - 1 || currentDifferenceIndex < view.getDifferenceCount() - 1); 237 } else { 238 nextAction.setEnabled(false); 239 } 240 prevAction.setEnabled(currentIndex > 0 || currentDifferenceIndex > 0); 241 } 242 243 public void addNotify() { 244 super.addNotify(); 245 if (refreshTask != null) { 246 Subversion.getInstance().getStatusCache().addVersioningListener(this); 247 } 248 JComponent parent = (JComponent) getParent(); 249 parent.getActionMap().put("jumpNext", nextAction); parent.getActionMap().put("jumpPrev", prevAction); } 252 253 public void removeNotify() { 254 Subversion.getInstance().getStatusCache().removeVersioningListener(this); 255 super.removeNotify(); 256 } 257 258 public void versioningEvent(VersioningEvent event) { 260 if (event.getId() == FileStatusCache.EVENT_FILE_STATUS_CHANGED) { 261 if (!affectsView(event)) { 262 return; 263 } 264 refreshTask.schedule(200); 265 } 266 } 267 268 private boolean affectsView(VersioningEvent event) { 269 File file = (File ) event.getParams()[0]; 270 FileInformation oldInfo = (FileInformation) event.getParams()[1]; 271 FileInformation newInfo = (FileInformation) event.getParams()[2]; 272 if (oldInfo == null) { 273 if ((newInfo.getStatus() & displayStatuses) == 0) return false; 274 } else { 275 if ((oldInfo.getStatus() & displayStatuses) + (newInfo.getStatus() & displayStatuses) == 0) return false; 276 } 277 return context.contains(file); 278 } 279 280 private void setDiffIndex(int idx, int location) { 281 currentIndex = idx; 282 DiffView view = setups[currentIndex].getView(); 283 284 final TopComponent tc = (TopComponent) getClientProperty(TopComponent.class); 286 if (tc != null) { 287 Node node = Node.EMPTY; 288 File baseFile = setups[currentIndex].getBaseFile(); 289 if (baseFile != null) { 290 FileObject fo = FileUtil.toFileObject(baseFile); 291 if (fo != null) { 292 node = new AbstractNode(Children.LEAF, Lookups.singleton(fo)); 293 } 294 } 295 final Node[] nodes = new Node[] {node}; 296 EventQueue.invokeLater(new Runnable () { 297 public void run() { 298 tc.setActivatedNodes(nodes); 299 } 300 }); 301 } 302 303 boolean focus = false; 304 boolean setDifference = false; 305 removeDiffComponent(); 306 if (view != null) { 307 if (location == -1) { 308 location = view.getDifferenceCount() - 1; 309 } 310 if (location >=0 && location < view.getDifferenceCount()) { 311 setDifference = true; 312 } 313 diffView = (JComponent) view.getComponent(); 314 diffView.getActionMap().put("jumpNext", nextAction); diffView.getActionMap().put("jumpPrev", prevAction); Component toc = WindowManager.getDefault().getRegistry().getActivated(); 317 if (SwingUtilities.isDescendingFrom(this, toc)) { 318 focus = true; 319 } 320 } else { 321 diffView = new SourcesUnavailableComponent(NbBundle.getMessage(DiffMainPanel.class, "MSG_DiffPanel_NoContent")); } 323 add(diffView); 324 delegatingUndoRedo.setDiffView(diffView); 325 326 currentDifferenceIndex = location; 327 if (navigationCombo.isVisible()) { 328 navigationCombo.setSelectedIndex(currentIndex); 329 } 330 refreshComponents(); 331 revalidate(); 332 repaint(); 333 if (focus) { 334 diffView.requestFocusInWindow(); 335 } 336 if (setDifference) { 338 final int finalLocation = location; 339 final DiffView finalView = view; 340 SwingUtilities.invokeLater(new Runnable () { 341 public void run() { 342 finalView.setCurrentDifference(finalLocation); 343 } 344 }); 345 } 346 } 347 348 private void removeDiffComponent() { 349 if (diffView != null) { 350 remove(diffView); 351 diffView = null; 352 } 353 } 354 355 public void actionPerformed(ActionEvent e) { 356 Object source = e.getSource(); 357 if (source == navigationCombo) onNavigationCombo(); 358 else if (source == refreshButton) onRefreshButton(); 359 else if (source == updateButton) onUpdateButton(); 360 else if (source == commitButton) onCommitButton(); 361 else if (source == localToggle || source == remoteToggle || source == allToggle) onDiffTypeChanged(); 362 } 363 364 private void onRefreshButton() { 365 if (context == null || context.getRoots().size() == 0) { 366 return; 367 } 368 369 if(executeStatusSupport!=null) { 370 executeStatusSupport.cancel(); 371 executeStatusSupport = null; 372 } 373 374 LifecycleManager.getDefault().saveAll(); 375 RequestProcessor rp = Subversion.getInstance().getRequestProcessor(); 376 executeStatusSupport = new SvnProgressSupport() { 377 public void perform() { 378 StatusAction.executeStatus(context, this); 379 } 380 }; 381 refreshSetups(); 382 } 383 384 private void onUpdateButton() { 385 UpdateAction.performUpdate(context); 386 } 387 388 private void onCommitButton() { 389 CommitAction.commit(contextName, context); 390 } 391 392 393 private void onNextButton() { 394 if (navigationCombo.isVisible()) { 395 currentIndex = navigationCombo.getSelectedIndex(); 396 } 397 398 DiffView view = setups[currentIndex].getView(); 399 if (view != null) { 400 int visibleDiffernce = view.getCurrentDifference(); 401 if (visibleDiffernce < view.getDifferenceCount() - 1) { 402 currentDifferenceIndex = Math.max(currentDifferenceIndex, visibleDiffernce); 403 } 404 if (++currentDifferenceIndex >= view.getDifferenceCount()) { 405 if (++currentIndex >= setups.length) { 406 currentIndex--; 407 } else { 408 setDiffIndex(currentIndex, 0); 409 } 410 } else { 411 view.setCurrentDifference(currentDifferenceIndex); 412 } 413 } else { 414 if (++currentIndex >= setups.length) currentIndex = 0; 415 setDiffIndex(currentIndex, 0); 416 } 417 refreshComponents(); 418 } 419 420 private void onPrevButton() { 421 DiffView view = setups[currentIndex].getView(); 422 if (view != null) { 423 if (--currentDifferenceIndex < 0) { 424 if (--currentIndex < 0) { 425 currentIndex++; 426 } else { 427 setDiffIndex(currentIndex, -1); 428 } 429 } else { 430 view.setCurrentDifference(currentDifferenceIndex); 431 } 432 } else { 433 if (--currentIndex < 0) currentIndex = setups.length - 1; 434 setDiffIndex(currentIndex, -1); 435 } 436 refreshComponents(); 437 } 438 439 private void onNavigationCombo() { 440 int idx = navigationCombo.getSelectedIndex(); 441 if (idx != currentIndex) setDiffIndex(idx, 0); 442 } 443 444 447 public Collection getSetups() { 448 if (setups == null) { 449 return Collections.EMPTY_SET; 450 } else { 451 return Arrays.asList(setups); 452 } 453 } 454 455 public String getSetupDisplayName() { 456 return contextName; 457 } 458 459 460 private void refreshSetups() { 461 if (dpt != null) { 462 prepareTask.cancel(); 463 } 464 465 File [] files; 466 switch (currentType) { 467 case Setup.DIFFTYPE_LOCAL: 468 displayStatuses = FileInformation.STATUS_LOCAL_CHANGE; 469 break; 470 case Setup.DIFFTYPE_REMOTE: 471 displayStatuses = FileInformation.STATUS_REMOTE_CHANGE; 472 break; 473 case Setup.DIFFTYPE_ALL: 474 displayStatuses = FileInformation.STATUS_LOCAL_CHANGE | FileInformation.STATUS_REMOTE_CHANGE; 475 break; 476 default: 477 throw new IllegalStateException ("Unknown DIFF type:" + currentType); } 479 files = SvnUtils.getModifiedFiles(context, displayStatuses); 480 481 Setup [] newSetups = new Setup[files.length]; 482 for (int i = 0; i < newSetups.length; i++) { 483 File file = files[i]; 484 newSetups[i] = new Setup(file, currentType); 485 } 486 Arrays.sort(newSetups, new SetupsComparator()); 487 488 setups = newSetups; 489 navigationCombo.setModel(new DefaultComboBoxModel(setups)); 490 491 if (setups.length == 0) { 492 String noContentLabel; 493 switch (currentType) { 494 case Setup.DIFFTYPE_LOCAL: 495 noContentLabel = NbBundle.getMessage(DiffMainPanel.class, "MSG_DiffPanel_NoLocalChanges"); break; 497 case Setup.DIFFTYPE_REMOTE: 498 noContentLabel = NbBundle.getMessage(DiffMainPanel.class, "MSG_DiffPanel_NoRemoteChanges"); break; 500 case Setup.DIFFTYPE_ALL: 501 noContentLabel = NbBundle.getMessage(DiffMainPanel.class, "MSG_DiffPanel_NoAllChanges"); break; 503 default: 504 throw new IllegalStateException ("Unknown DIFF type:" + currentType); } 506 setups = null; 507 navigationCombo.setModel(new DefaultComboBoxModel(new Object [] { noContentLabel })); 508 navigationCombo.setEnabled(false); 509 navigationCombo.setPreferredSize(null); 510 Dimension dim = navigationCombo.getPreferredSize(); 511 navigationCombo.setPreferredSize(new Dimension(dim.width + 1, dim.height)); 512 removeDiffComponent(); 513 diffView = new SourcesUnavailableComponent(noContentLabel); 514 add(diffView); 515 nextAction.setEnabled(false); 516 prevAction.setEnabled(false); 517 revalidate(); 518 repaint(); 519 } else { 520 navigationCombo.setEnabled(true); 521 navigationCombo.setPreferredSize(null); 522 Dimension dim = navigationCombo.getPreferredSize(); 523 navigationCombo.setPreferredSize(new Dimension(dim.width + 1, dim.height)); 524 setDiffIndex(0, 0); 525 dpt = new DiffPrepareTask(setups); 526 prepareTask = RequestProcessor.getDefault().post(dpt); 527 } 528 } 529 530 private void onDiffTypeChanged() { 531 if (localToggle.isSelected()) { 532 if (currentType == Setup.DIFFTYPE_LOCAL) return; 533 currentType = Setup.DIFFTYPE_LOCAL; 534 } else if (remoteToggle.isSelected()) { 535 if (currentType == Setup.DIFFTYPE_REMOTE) return; 536 currentType = Setup.DIFFTYPE_REMOTE; 537 } else if (allToggle.isSelected()) { 538 if (currentType == Setup.DIFFTYPE_ALL) return; 539 currentType = Setup.DIFFTYPE_ALL; 540 } 541 refreshSetups(); 542 } 543 544 549 private void initComponents() { 551 controlsToolbar = new javax.swing.JToolBar (); 552 allToggle = new javax.swing.JToggleButton (); 553 localToggle = new javax.swing.JToggleButton (); 554 remoteToggle = new javax.swing.JToggleButton (); 555 navigationCombo = new javax.swing.JComboBox (); 556 nextButton = new javax.swing.JButton (); 557 prevButton = new javax.swing.JButton (); 558 jPanel1 = new javax.swing.JPanel (); 559 refreshButton = new javax.swing.JButton (); 560 updateButton = new javax.swing.JButton (); 561 commitButton = new javax.swing.JButton (); 562 563 setLayout(new java.awt.BorderLayout ()); 564 565 controlsToolbar.setFloatable(false); 566 org.openide.awt.Mnemonics.setLocalizedText(allToggle, org.openide.util.NbBundle.getBundle(DiffMainPanel.class).getString("CTL_DiffPanel_All")); java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("org/netbeans/modules/subversion/ui/diff/Bundle"); allToggle.setToolTipText(bundle.getString("CTL_DiffPanel_All_Tooltip")); controlsToolbar.add(allToggle); 570 571 org.openide.awt.Mnemonics.setLocalizedText(localToggle, org.openide.util.NbBundle.getBundle(DiffMainPanel.class).getString("CTL_DiffPanel_Local")); localToggle.setToolTipText(bundle.getString("CTL_DiffPanel_Local_Tooltip")); controlsToolbar.add(localToggle); 574 575 org.openide.awt.Mnemonics.setLocalizedText(remoteToggle, bundle.getString("CTL_DiffPanel_Remote")); remoteToggle.setToolTipText(bundle.getString("CTL_DiffPanel_Remote_Tooltip")); controlsToolbar.add(remoteToggle); 578 579 controlsToolbar.add(navigationCombo); 580 navigationCombo.getAccessibleContext().setAccessibleName("Navigation list"); 581 navigationCombo.getAccessibleContext().setAccessibleDescription("Navigation list"); 582 583 nextButton.setIcon(new javax.swing.ImageIcon (getClass().getResource("/org/netbeans/modules/subversion/resources/icons/diff-next.png"))); 584 nextButton.setToolTipText(bundle.getString("CTL_DiffPanel_Next_Tooltip")); nextButton.setEnabled(false); 586 controlsToolbar.add(nextButton); 587 nextButton.getAccessibleContext().setAccessibleName("Go to next"); 588 589 prevButton.setIcon(new javax.swing.ImageIcon (getClass().getResource("/org/netbeans/modules/subversion/resources/icons/diff-prev.png"))); 590 prevButton.setToolTipText(bundle.getString("CTL_DiffPanel_Prev_Tooltip")); prevButton.setEnabled(false); 592 controlsToolbar.add(prevButton); 593 prevButton.getAccessibleContext().setAccessibleName("Go to previous"); 594 595 jPanel1.setMaximumSize(new java.awt.Dimension (15, 1)); 596 jPanel1.setPreferredSize(new java.awt.Dimension (15, 1)); 597 controlsToolbar.add(jPanel1); 598 599 refreshButton.setIcon(new javax.swing.ImageIcon (getClass().getResource("/org/netbeans/modules/subversion/resources/icons/refresh.png"))); 600 refreshButton.setToolTipText(bundle.getString("MSG_RefreshDiff_Tooltip")); controlsToolbar.add(refreshButton); 602 refreshButton.getAccessibleContext().setAccessibleName("Refresh"); 603 604 updateButton.setIcon(new javax.swing.ImageIcon (getClass().getResource("/org/netbeans/modules/subversion/resources/icons/update.png"))); 605 updateButton.setToolTipText(bundle.getString("CTL_DiffPanel_Update_Tooltip")); controlsToolbar.add(updateButton); 607 updateButton.getAccessibleContext().setAccessibleName("Update All"); 608 updateButton.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getBundle(DiffMainPanel.class).getString("CTL_Diff_DiffAll")); 610 commitButton.setIcon(new javax.swing.ImageIcon (getClass().getResource("/org/netbeans/modules/subversion/resources/icons/commit.png"))); 611 commitButton.setToolTipText(bundle.getString("CTL_DiffPanel_Commit_Tooltip")); controlsToolbar.add(commitButton); 613 commitButton.getAccessibleContext().setAccessibleName("Commit All"); 614 commitButton.getAccessibleContext().setAccessibleDescription("Commit All Chnages"); 615 616 add(controlsToolbar, java.awt.BorderLayout.NORTH); 617 618 } 620 private javax.swing.JToggleButton allToggle; 622 private javax.swing.JButton commitButton; 623 private javax.swing.JToolBar controlsToolbar; 624 private javax.swing.JPanel jPanel1; 625 private javax.swing.JToggleButton localToggle; 626 private javax.swing.JComboBox navigationCombo; 627 private javax.swing.JButton nextButton; 628 private javax.swing.JButton prevButton; 629 private javax.swing.JButton refreshButton; 630 private javax.swing.JToggleButton remoteToggle; 631 private javax.swing.JButton updateButton; 632 634 635 private class DiffPrepareTask implements Runnable { 636 637 private final Setup[] prepareSetups; 638 639 public DiffPrepareTask(Setup [] prepareSetups) { 640 this.prepareSetups = prepareSetups; 641 } 642 643 public void run() { 644 final Diff diff = Diff.getDefault(); 645 for (int i = 0; i < prepareSetups.length; i++) { 646 if (prepareSetups != setups) return; 647 final int fi = i; 648 649 try { 650 StreamSource ss1, ss2; 651 prepareSetups[i].initSources(); ss1 = prepareSetups[fi].getFirstSource(); 653 ss2 = prepareSetups[fi].getSecondSource(); 654 DiffView view = diff.createDiff(ss1, ss2); 656 List propDiffViews = propertyDiffViews(prepareSetups[fi]); 657 DiffView[] views = new DiffView[propDiffViews.size() +1]; 658 views[0] = view; 659 for (int v=0; v<propDiffViews.size(); v++) { 660 views[v+1] = (DiffView) propDiffViews.get(v); 661 } 662 view = new MultiDiffView(views, DiffMainPanel.this); 663 664 final DiffView finalDiffView = view; 665 SwingUtilities.invokeLater(new Runnable () { 666 public void run() { 667 prepareSetups[fi].setView(finalDiffView); 668 if (prepareSetups != setups) { 669 return; 670 } 671 if (currentIndex == fi) { 672 setDiffIndex(fi, 0); 673 } 674 } 675 }); 676 } catch (IOException e) { 677 ErrorManager.getDefault().notify(e); 678 } 679 } 680 } 681 } 682 683 689 private List <DiffView> propertyDiffViews(Setup setup) { 690 final Diff diff = Diff.getDefault(); 691 List <DiffView> propDiffViews = getEmptyList(); 692 if (currentType == Setup.DIFFTYPE_LOCAL || 693 currentType == Setup.DIFFTYPE_ALL) { 694 DiffProvider diffAlgorithm = (DiffProvider) Lookup.getDefault().lookup(DiffProvider.class); 695 try { 696 File base = setup.getBaseFile(); 697 PropertiesClient client = new PropertiesClient(base); 698 Map<String , byte[]> baseProps = client.getBaseProperties(); 699 Map<String , byte[]> localProps = client.getProperties(); 700 701 703 Set<String > allProps = new TreeSet<String >(localProps.keySet()); 704 allProps.addAll(baseProps.keySet()); 705 propDiffViews = new ArrayList<DiffView>(allProps.size()); 706 Iterator<String > it = allProps.iterator(); 707 while(it.hasNext()) { 708 String key = it.next(); 709 boolean isBase = baseProps.containsKey(key); 710 boolean isLocal = localProps.containsKey(key); 711 if (isBase && isLocal) { 712 Property p1 = new Property(baseProps.get(key)); 713 Property p2 = new Property(localProps.get(key)); 714 Difference[] diffs = diffAlgorithm.computeDiff(p1.toReader(), p2.toReader()); 715 if (diff != null && diffs.length != 0) { 716 StreamSource ps1 = StreamSource.createSource(key, NbBundle.getMessage(DiffMainPanel.class, "LBL_Diff_PropertyBase", key), p1.getMIME(), p1.toReader()); StreamSource ps2 = StreamSource.createSource(key, NbBundle.getMessage(DiffMainPanel.class, "LBL_Diff_PropertyLocallyModified", key), p2.getMIME(), p2.toReader()); propDiffViews.add(diff.createDiff(ps1, ps2)); 719 } 720 } else if (isBase) { 721 Property p1 = new Property(baseProps.get(key)); 723 Reader r2 = new StringReader(""); StreamSource ps1 = StreamSource.createSource(key, NbBundle.getMessage(DiffMainPanel.class, "LBL_Diff_PropertyBase", key), p1.getMIME(), p1.toReader()); StreamSource ps2 = StreamSource.createSource(key, NbBundle.getMessage(DiffMainPanel.class, "LBL_Diff_PropertyLocallyDeleted", key), "text/plain", r2); propDiffViews.add(diff.createDiff(ps1, ps2)); 727 } else { 728 Reader r1 = new StringReader(""); Property p2 = new Property(localProps.get(key)); 730 StreamSource ps1 = StreamSource.createSource(key, NbBundle.getMessage(DiffMainPanel.class, "LBL_Diff_Property", key), "text/plain", r1); StreamSource ps2 = StreamSource.createSource(key, NbBundle.getMessage(DiffMainPanel.class, "LBL_Diff_PropertyLocallyNew", key), p2.getMIME(), p2.toReader()); propDiffViews.add(diff.createDiff(ps1, ps2)); 733 } 734 } 735 736 } catch (IOException ex) { 737 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex); 738 } 739 740 } else { 741 ErrorManager.getDefault().log("subversion.DiffMainPanel does not support remote property retrievals"); } 743 return propDiffViews; 744 } 745 746 private static final List <DiffView> getEmptyList() { 747 return Collections.emptyList(); 748 } 749 750 751 static class Property { 752 final byte[] value; 753 754 Property(Object value) { 755 this.value = (byte[]) value; 756 } 757 758 String getMIME() { 759 return "text/plain"; } 761 762 Reader toReader() { 763 if (SvnUtils.isBinary(value)) { 764 return new StringReader(NbBundle.getMessage(DiffMainPanel.class, "LBL_Diff_NoBinaryDiff")); } else { 766 try { 767 return new InputStreamReader(new ByteArrayInputStream(value), "utf8"); } catch (UnsupportedEncodingException ex) { 769 ErrorManager.getDefault().notify(ex); 770 return new StringReader("[ERROR: " + ex.getLocalizedMessage() + "]"); } 772 } 773 } 774 } 775 776 private static class SourcesUnavailableComponent extends JComponent { 777 778 public SourcesUnavailableComponent(String message) { 779 JLabel label = new JLabel(message); 780 setLayout(new BorderLayout()); 781 label.setHorizontalAlignment(JLabel.CENTER); 782 add(label, BorderLayout.CENTER); 783 } 784 } 785 786 796 private class ToolbarLayout implements LayoutManager { 797 798 799 private int TOOLBAR_HEIGHT_ADJUSTMENT = 10; 800 801 private int TOOLBAR_SEPARATOR_MIN_WIDTH = 12; 802 803 804 private int toolbarHeight = -1; 805 806 807 private Dimension parentSize; 808 809 private Set<JComponent> adjusted = new HashSet<JComponent>(); 810 811 public void removeLayoutComponent(Component comp) { 812 } 813 814 public void layoutContainer(Container parent) { 815 Rectangle [] sizes = layout(parent); 816 for (int i = 0; i < sizes.length; i++) { 817 JComponent comp = (JComponent) parent.getComponent(i); 818 if (comp.isVisible()) { 819 comp.setBounds(sizes[i]); 820 } 821 } 822 } 823 824 private Rectangle [] layout(Container parent) { 825 Dimension dim = DiffMainPanel.this.getSize(); 826 Dimension max = parent.getSize(); 827 int rowOffset = 0; 828 int maxHeigth = 0; 829 830 List <Rectangle> sizes = new ArrayList<Rectangle>(); 831 int components = parent.getComponentCount(); 832 int horizont = 0; 833 for (int i = 0; i < components; i++) { 834 Rectangle rect = new Rectangle(); 835 JComponent comp = (JComponent) parent.getComponent(i); 836 if (comp.isVisible()) { 837 rect.setLocation(horizont, rowOffset); 838 if (comp instanceof AbstractButton) { 839 adjustToobarButton((AbstractButton)comp); 840 } else { 841 adjustToolbarComponentSize(comp); 842 } 843 Dimension pref = comp.getPreferredSize(); 844 int width = pref.width; 845 if (comp instanceof JSeparator && ((dim.height - dim.width) <= 0)) { 846 width = Math.max(width, TOOLBAR_SEPARATOR_MIN_WIDTH); 847 } 848 849 int height = getToolbarHeight(dim) -1; 851 maxHeigth = Math.max(maxHeigth, height); 852 rect.setSize(width, height); horizont += width; 854 if (horizont > max.width) { 855 rowOffset += maxHeigth + 2; 856 horizont = 0; 857 maxHeigth = 0; 858 } 859 } 860 sizes.add(rect); 861 } 862 return sizes.toArray(new Rectangle[sizes.size()]); 863 } 864 865 public void addLayoutComponent(String name, Component comp) { 866 } 867 868 public Dimension minimumLayoutSize(Container parent) { 869 870 Dimension dim = DiffMainPanel.this.getSize(); 872 int height = getToolbarHeight(dim); 873 874 int components = parent.getComponentCount(); 875 int horizont = 0; 876 for (int i = 0; i<components; i++) { 877 Component comp = parent.getComponent(i); 878 if (comp.isVisible() == false) continue; 879 if (comp instanceof AbstractButton) { 880 adjustToobarButton((AbstractButton)comp); 881 } else { 882 adjustToolbarComponentSize((JComponent)comp); 883 } 884 Dimension pref = comp.getPreferredSize(); 885 int width = pref.width; 886 if (comp instanceof JSeparator && ((dim.height - dim.width) <= 0)) { 887 width = Math.max(width, TOOLBAR_SEPARATOR_MIN_WIDTH); 888 } 889 horizont += width; 890 } 891 892 return new Dimension(horizont, height); 893 } 894 895 public Dimension preferredLayoutSize(Container parent) { 896 Rectangle [] bounds = layout(parent); 897 Rectangle union = new Rectangle(); 898 for (int i = 0; i < bounds.length; i++) { 899 union.add(bounds[i]); 900 } 901 return new Dimension(union.width, union.height); 902 } 903 904 908 private int getToolbarHeight(Dimension parent) { 909 910 if (parentSize == null || (parentSize.equals(parent) == false)) { 911 parentSize = parent; 912 toolbarHeight = -1; 913 } 914 915 if (toolbarHeight == -1) { 916 BufferedImage image = new BufferedImage (1,1,BufferedImage.TYPE_BYTE_GRAY); 917 Graphics2D g = image.createGraphics(); 918 UIDefaults def = UIManager.getLookAndFeelDefaults(); 919 920 int height = 0; 921 String [] fonts = {"Label.font", "Button.font", "ToggleButton.font"}; for (int i=0; i<fonts.length; i++) { 923 Font f = def.getFont(fonts[i]); 924 FontMetrics fm = g.getFontMetrics(f); 925 height = Math.max(height, fm.getHeight()); 926 } 927 toolbarHeight = height + TOOLBAR_HEIGHT_ADJUSTMENT; 928 } 929 930 return toolbarHeight; 931 } 932 933 934 935 private void adjustToobarButton(final AbstractButton button) { 936 937 if (adjusted.contains(button)) return; 938 939 if (button instanceof JToggleButton == false) { 943 button.setContentAreaFilled(false); 944 button.setMargin(new Insets(0, 3, 0, 3)); 945 button.setBorderPainted(false); 946 button.addMouseListener(new MouseAdapter() { 947 public void mouseEntered(MouseEvent e) { 948 button.setContentAreaFilled(true); 949 button.setBorderPainted(true); 950 } 951 952 public void mouseExited(MouseEvent e) { 953 button.setContentAreaFilled(false); 954 button.setBorderPainted(false); 955 } 956 }); 957 } 958 959 adjustToolbarComponentSize(button); 960 } 961 962 private void adjustToolbarComponentSize(JComponent button) { 963 964 if (adjusted.contains(button)) return; 965 966 if (button.getBorder() instanceof CompoundBorder ) { Dimension pref = button.getPreferredSize(); 969 970 if ("Windows".equals(UIManager.getLookAndFeel().getID())) { pref.width += 9; 973 } 974 button.setPreferredSize(pref); 975 } 976 977 adjusted.add(button); 978 } 979 } 980 981 private static class SetupsComparator implements Comparator<Setup> { 982 983 private SvnUtils.ByImportanceComparator delegate = new SvnUtils.ByImportanceComparator(); 984 private FileStatusCache cache; 985 986 public SetupsComparator() { 987 cache = Subversion.getInstance().getStatusCache(); 988 } 989 990 public int compare(Setup setup1, Setup setup2) { 991 int cmp = delegate.compare(cache.getStatus(setup1.getBaseFile()), cache.getStatus(setup2.getBaseFile())); 992 if (cmp == 0) { 993 return setup1.getBaseFile().getName().compareToIgnoreCase(setup2.getBaseFile().getName()); 994 } 995 return cmp; 996 } 997 } 998 999 private class RefreshViewTask implements Runnable { 1000 public void run() { 1001 SwingUtilities.invokeLater(new Runnable () { 1002 public void run() { 1003 refreshSetups(); 1004 } 1005 }); 1006 } 1007 } 1008} 1009 | Popular Tags |