KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > versioning > system > cvss > ui > actions > diff > DiffMainPanel


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.versioning.system.cvss.ui.actions.diff;
21
22 import org.netbeans.api.diff.Diff;
23 import org.netbeans.api.diff.DiffView;
24 import org.netbeans.api.diff.StreamSource;
25 import org.netbeans.modules.versioning.system.cvss.*;
26 import org.netbeans.modules.versioning.system.cvss.ui.actions.update.UpdateExecutor;
27 import org.netbeans.modules.versioning.system.cvss.ui.actions.commit.CommitAction;
28 import org.netbeans.modules.versioning.system.cvss.util.Utils;
29 import org.netbeans.modules.versioning.system.cvss.util.Context;
30 import org.netbeans.modules.versioning.util.VersioningListener;
31 import org.netbeans.modules.versioning.util.VersioningEvent;
32 import org.netbeans.modules.versioning.util.DelegatingUndoRedo;
33 import org.netbeans.lib.cvsclient.command.update.UpdateCommand;
34 import org.netbeans.lib.cvsclient.command.GlobalOptions;
35 import org.openide.util.NbBundle;
36 import org.openide.util.RequestProcessor;
37 import org.openide.util.lookup.Lookups;
38 import org.openide.ErrorManager;
39 import org.openide.LifecycleManager;
40 import org.openide.awt.UndoRedo;
41 import org.openide.nodes.Node;
42 import org.openide.nodes.AbstractNode;
43 import org.openide.nodes.Children;
44 import org.openide.windows.TopComponent;
45 import org.openide.windows.WindowManager;
46 import org.openide.filesystems.FileObject;
47 import org.openide.filesystems.FileUtil;
48
49 import javax.swing.*;
50 import javax.swing.plaf.basic.BasicComboBoxRenderer JavaDoc;
51 import javax.swing.border.CompoundBorder JavaDoc;
52 import java.io.IOException JavaDoc;
53 import java.io.File JavaDoc;
54 import java.util.*;
55 import java.util.List JavaDoc;
56 import java.awt.event.*;
57 import java.awt.*;
58 import java.awt.image.BufferedImage JavaDoc;
59
60 /**
61  * Main DIFF GUI panel that includes the navidation toolbar and DIFF component.
62  *
63  * @author Maros Sandor
64  */

65 public class DiffMainPanel extends javax.swing.JPanel JavaDoc implements ActionListener, VersioningListener, DiffSetupSource {
66
67     /**
68      * Array of DIFF setups that we show in the DIFF view. Contents of this array is changed if
69      * the user switches DIFF types.
70      */

71     private Setup[] setups;
72     
73     private final DelegatingUndoRedo delegatingUndoRedo = new DelegatingUndoRedo();
74
75     /**
76      * Context in which to DIFF.
77      */

78     private final Context context;
79
80     private int displayStatuses;
81
82     /**
83      * Display name of the context of this diff.
84      */

85     private final String JavaDoc contextName;
86     
87     private int currentType;
88     private int currentDifferenceIndex;
89     private int currentIndex = -1;
90     
91     private RequestProcessor.Task prepareTask;
92     private DiffPrepareTask dpt;
93
94     private AbstractAction nextAction;
95     private AbstractAction prevAction;
96     
97     // TODO: reuse this code ... the same pattern is in SynchronizePanel
98
private static final RequestProcessor rp = new RequestProcessor("CVS-VersioningView", 1); // NOI18N
99

100     /**
101      * null for view that are not
102      */

103     private RequestProcessor.Task refreshTask;
104
105     private ExecutorGroup group;
106     private volatile boolean executed;
107
108     private JComponent diffView;
109
110     /**
111      * Creates diff panel and immediatelly starts loading...
112      */

113     public DiffMainPanel(Context context, int initialType, String JavaDoc contextName, ExecutorGroup group) {
114         this.context = context;
115         this.contextName = contextName;
116         this.group = group;
117         currentType = initialType;
118         initComponents();
119         setupComponents();
120         refreshSetups();
121         refreshComponents();
122         refreshTask = rp.create(new RefreshViewTask());
123     }
124
125     /**
126      * Construct diff component showing just one file.
127      * It hides All, Local, Remote toggles and file chooser combo.
128      */

129     public DiffMainPanel(File JavaDoc file, String JavaDoc rev1, String JavaDoc rev2) {
130         context = null;
131         contextName = file.getName();
132         initComponents();
133         setupComponents();
134         localToggle.setVisible(false);
135         remoteToggle.setVisible(false);
136         allToggle.setVisible(false);
137         navigationCombo.setVisible(false);
138         refreshButton.setVisible(false);
139         updateButton.setVisible(false);
140         commitButton.setVisible(false);
141
142         // mimics refreshSetups()
143
setups = new Setup[] {
144             new Setup(file, rev1, rev2)
145         };
146         setDiffIndex(0, 0);
147         dpt = new DiffPrepareTask(setups);
148         prepareTask = RequestProcessor.getDefault().post(dpt);
149     }
150
151     UndoRedo getUndoRedo() {
152         return delegatingUndoRedo;
153     }
154
155     /**
156      * Called by the enclosing TopComponent to interrupt the fetching task.
157      */

158     void componentClosed() {
159         setups = null;
160         if (prepareTask != null) {
161             prepareTask.cancel();
162         }
163     }
164
165     public synchronized void setGroup(ExecutorGroup group) {
166         this.group = group;
167         if (executed) {
168             group.executed();
169         }
170     }
171
172     void requestActive() {
173         if (diffView != null) {
174             diffView.requestFocusInWindow();
175         }
176     }
177
178     private static class ColoredComboRenderer extends BasicComboBoxRenderer JavaDoc {
179
180         public Component getListCellRendererComponent(JList list, Object JavaDoc value, int index, boolean isSelected, boolean cellHasFocus) {
181             if (isSelected) {
182                 value = ((Setup) value).getBaseFile().getName();
183             }
184             return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
185         }
186     }
187
188     private void setupComponents() {
189         controlsToolbar.putClientProperty("JToolBar.isRollover", Boolean.TRUE); // NOI18N
190
controlsToolbar.setLayout(new DiffMainPanel.ToolbarLayout());
191         
192         navigationCombo.addActionListener(this);
193         navigationCombo.setRenderer(new ColoredComboRenderer());
194         refreshButton.addActionListener(this);
195         updateButton.addActionListener(this);
196         commitButton.addActionListener(this);
197         localToggle.addActionListener(this);
198         remoteToggle.addActionListener(this);
199         allToggle.addActionListener(this);
200         
201         refreshButton.setToolTipText(NbBundle.getMessage(DiffMainPanel.class, "MSG_RefreshDiff_Tooltip"));
202         updateButton.setToolTipText(NbBundle.getMessage(DiffMainPanel.class, "MSG_UpdateDiff_Tooltip", contextName));
203         commitButton.setToolTipText(NbBundle.getMessage(DiffMainPanel.class, "MSG_CommitDiff_Tooltip", contextName));
204         ButtonGroup grp = new ButtonGroup();
205         grp.add(localToggle);
206         grp.add(remoteToggle);
207         grp.add(allToggle);
208         if (currentType == Setup.DIFFTYPE_LOCAL) localToggle.setSelected(true);
209         else if (currentType == Setup.DIFFTYPE_REMOTE) remoteToggle.setSelected(true);
210         else if (currentType == Setup.DIFFTYPE_ALL) allToggle.setSelected(true);
211         
212         nextAction = new AbstractAction(null, new javax.swing.ImageIcon JavaDoc(getClass().getResource("/org/netbeans/modules/versioning/system/cvss/resources/icons/diff-next.png"))) { // NOI18N
213
{
214                 putValue(Action.SHORT_DESCRIPTION, java.util.ResourceBundle.getBundle("org/netbeans/modules/versioning/system/cvss/ui/actions/diff/Bundle").
215                                                    getString("CTL_DiffPanel_Next_Tooltip"));
216             }
217             public void actionPerformed(ActionEvent e) {
218                 onNextButton();
219             }
220         };
221         prevAction = new AbstractAction(null, new javax.swing.ImageIcon JavaDoc(getClass().getResource("/org/netbeans/modules/versioning/system/cvss/resources/icons/diff-prev.png"))) { // NOI18N
222
{
223                 putValue(Action.SHORT_DESCRIPTION, java.util.ResourceBundle.getBundle("org/netbeans/modules/versioning/system/cvss/ui/actions/diff/Bundle").
224                                                    getString("CTL_DiffPanel_Prev_Tooltip"));
225             }
226             public void actionPerformed(ActionEvent e) {
227                 onPrevButton();
228             }
229         };
230         nextButton.setAction(nextAction);
231         prevButton.setAction(prevAction);
232     }
233     
234     private void refreshComponents() {
235         DiffView view = setups != null ? setups[currentIndex].getView() : null;
236         if (view != null) {
237             nextAction.setEnabled(currentIndex < setups.length - 1 || currentDifferenceIndex < view.getDifferenceCount() - 1);
238         } else {
239             nextAction.setEnabled(false);
240         }
241         prevAction.setEnabled(currentIndex > 0 || currentDifferenceIndex > 0);
242     }
243     
244     public void addNotify() {
245         super.addNotify();
246         if (refreshTask != null) {
247             CvsVersioningSystem.getInstance().getStatusCache().addVersioningListener(this);
248         }
249         JComponent parent = (JComponent) getParent();
250         parent.getActionMap().put("jumpNext", nextAction); // NOI18N
251
parent.getActionMap().put("jumpPrev", prevAction); // NOI18N
252
}
253
254     public void removeNotify() {
255         CvsVersioningSystem.getInstance().getStatusCache().removeVersioningListener(this);
256         super.removeNotify();
257     }
258     
259     // TODO: reuse this code ... the same pattern is in SynchronizePanel
260
public void versioningEvent(VersioningEvent event) {
261         if (event.getId() == FileStatusCache.EVENT_FILE_STATUS_CHANGED) {
262             if (!affectsView(event)) return;
263             if (CvsVersioningSystem.getInstance().getParameter(CvsVersioningSystem.PARAM_BATCH_REFRESH_RUNNING) != null) {
264                 refreshTask.schedule(1000);
265             } else {
266                 refreshTask.schedule(200);
267             }
268         } else if (event.getId() == CvsVersioningSystem.EVENT_PARAM_CHANGED) {
269             if (event.getParams()[0].equals(CvsVersioningSystem.PARAM_BATCH_REFRESH_RUNNING)) {
270                 if (CvsVersioningSystem.getInstance().getParameter(CvsVersioningSystem.PARAM_BATCH_REFRESH_RUNNING) == null) {
271                     refreshTask.schedule(0);
272                 }
273             }
274         }
275     }
276     
277     private boolean affectsView(VersioningEvent event) {
278         File JavaDoc file = (File JavaDoc) event.getParams()[0];
279         FileInformation oldInfo = (FileInformation) event.getParams()[1];
280         FileInformation newInfo = (FileInformation) event.getParams()[2];
281         if (oldInfo == null) {
282             if ((newInfo.getStatus() & displayStatuses) == 0) return false;
283         } else {
284             if ((oldInfo.getStatus() & displayStatuses) + (newInfo.getStatus() & displayStatuses) == 0) return false;
285         }
286         return context.contains(file);
287     }
288     
289     private void setDiffIndex(int idx, int location) {
290         currentIndex = idx;
291         DiffView view = setups[currentIndex].getView();
292
293         // enable Select in .. action
294
TopComponent tc = (TopComponent) getClientProperty(TopComponent.class);
295         if (tc != null) {
296             Node node = Node.EMPTY;
297             File JavaDoc baseFile = setups[currentIndex].getBaseFile();
298             if (baseFile != null) {
299                 FileObject fo = FileUtil.toFileObject(baseFile);
300                 if (fo != null) {
301                     node = new AbstractNode(Children.LEAF, Lookups.singleton(fo));
302                 }
303             }
304             tc.setActivatedNodes(new Node[] {node});
305         }
306
307         boolean focus = false;
308         removeDiffComponent();
309         if (view != null) {
310             if (location == -1) {
311                 location = view.getDifferenceCount() - 1;
312             }
313             if (location >=0 && location < view.getDifferenceCount()) {
314                 view.setCurrentDifference(location);
315             }
316             diffView = (JComponent) view.getComponent();
317             diffView.getActionMap().put("jumpNext", nextAction); // NOI18N
318
diffView.getActionMap().put("jumpPrev", prevAction); // NOI18N
319
Component toc = WindowManager.getDefault().getRegistry().getActivated();
320             if (SwingUtilities.isDescendingFrom(this, toc)) {
321                 focus = true;
322             }
323         } else {
324             diffView = new SourcesUnavailableComponent(NbBundle.getMessage(DiffMainPanel.class, "MSG_DiffPanel_NoContent"));
325         }
326         add(diffView);
327         delegatingUndoRedo.setDiffView(diffView);
328
329         currentDifferenceIndex = location;
330         if (navigationCombo.isVisible()) {
331             navigationCombo.setSelectedIndex(currentIndex);
332         }
333         refreshComponents();
334         revalidate();
335         repaint();
336         if (focus) {
337             diffView.requestFocusInWindow();
338         }
339     }
340
341     private void removeDiffComponent() {
342         if (diffView != null) {
343             remove(diffView);
344             diffView = null;
345         }
346     }
347
348     public void actionPerformed(ActionEvent e) {
349         Object JavaDoc source = e.getSource();
350         if (source == navigationCombo) onNavigationCombo();
351         else if (source == refreshButton) onRefreshButton();
352         else if (source == updateButton) onUpdateButton();
353         else if (source == commitButton) onCommitButton();
354         else if (source == localToggle || source == remoteToggle || source == allToggle) onDiffTypeChanged();
355     }
356
357     private void onRefreshButton() {
358         LifecycleManager.getDefault().saveAll();
359         refreshSetups();
360         executeUpdateCommand(true);
361     }
362
363     private void onUpdateButton() {
364         LifecycleManager.getDefault().saveAll();
365         executeUpdateCommand(false);
366     }
367
368     private void onCommitButton() {
369         LifecycleManager.getDefault().saveAll();
370         CommitAction.invokeCommit(contextName, context, null);
371     }
372
373     // TODO: reuse this code ... the same pattern is in SynchronizePanel
374
private void executeUpdateCommand(boolean doNoChanges) {
375         if (context == null || context.getRootFiles().length == 0) return;
376         UpdateCommand cmd = new UpdateCommand();
377         String JavaDoc msg;
378         if (doNoChanges) {
379             msg = NbBundle.getMessage(DiffMainPanel.class, "BK0001");
380         } else {
381             msg = NbBundle.getMessage(DiffMainPanel.class, "BK0002");
382         }
383         cmd.setDisplayName(msg);
384         GlobalOptions options = CvsVersioningSystem.createGlobalOptions();
385         if (context.getExclusions().size() > 0) {
386             options.setExclusions((File JavaDoc[]) context.getExclusions().toArray(new File JavaDoc[context.getExclusions().size()]));
387         }
388         cmd.setFiles(context.getRootFiles());
389         cmd.setBuildDirectories(true);
390         cmd.setPruneDirectories(true);
391         options.setDoNoChanges(doNoChanges);
392
393         ExecutorGroup group = new ExecutorGroup(msg);
394         group.addExecutors(UpdateExecutor.splitCommand(cmd, CvsVersioningSystem.getInstance(), options, contextName));
395         group.execute();
396     }
397
398     /** Next that is driven by visibility. It continues to next not yet visible difference. */
399     private void onNextButton() {
400         if (navigationCombo.isVisible()) {
401             currentIndex = navigationCombo.getSelectedIndex();
402         }
403
404         DiffView view = setups[currentIndex].getView();
405         if (view != null) {
406             int visibleDiffernce = view.getCurrentDifference();
407             if (visibleDiffernce < view.getDifferenceCount() - 1) {
408                 currentDifferenceIndex = Math.max(currentDifferenceIndex, visibleDiffernce);
409             }
410             if (++currentDifferenceIndex >= view.getDifferenceCount()) {
411                 if (++currentIndex >= setups.length) {
412                     currentIndex--;
413                 } else {
414                     setDiffIndex(currentIndex, 0);
415                 }
416             } else {
417                 view.setCurrentDifference(currentDifferenceIndex);
418             }
419         } else {
420             if (++currentIndex >= setups.length) currentIndex = 0;
421             setDiffIndex(currentIndex, 0);
422         }
423         refreshComponents();
424     }
425
426     private void onPrevButton() {
427         DiffView view = setups[currentIndex].getView();
428         if (view != null) {
429             if (--currentDifferenceIndex < 0) {
430                 if (--currentIndex < 0) {
431                     currentIndex++;
432                 } else {
433                     setDiffIndex(currentIndex, -1);
434                 }
435             } else {
436                 view.setCurrentDifference(currentDifferenceIndex);
437             }
438         } else {
439             if (--currentIndex < 0) currentIndex = setups.length - 1;
440             setDiffIndex(currentIndex, -1);
441         }
442         refreshComponents();
443     }
444
445     private void onNavigationCombo() {
446         int idx = navigationCombo.getSelectedIndex();
447         if (idx != currentIndex) setDiffIndex(idx, 0);
448     }
449
450     /**
451      * @return setups, takes into account Local, Remote, All switch
452      */

453     public Collection getSetups() {
454         if (setups == null) {
455             return Collections.EMPTY_SET;
456         } else {
457             return Arrays.asList(setups);
458         }
459     }
460
461     public String JavaDoc getSetupDisplayName() {
462         return contextName;
463     }
464
465
466     private void refreshSetups() {
467         if (dpt != null) {
468             prepareTask.cancel();
469         }
470
471         File JavaDoc [] files;
472         switch (currentType) {
473         case Setup.DIFFTYPE_LOCAL:
474             displayStatuses = FileInformation.STATUS_LOCAL_CHANGE;
475             break;
476         case Setup.DIFFTYPE_REMOTE:
477             displayStatuses = FileInformation.STATUS_REMOTE_CHANGE;
478             break;
479         case Setup.DIFFTYPE_ALL:
480             displayStatuses = FileInformation.STATUS_LOCAL_CHANGE | FileInformation.STATUS_REMOTE_CHANGE;
481             break;
482         default:
483             throw new IllegalStateException JavaDoc("Unknown DIFF type:" + currentType); // NOI18N
484
}
485         files = DiffExecutor.getModifiedFiles(context, displayStatuses);
486         
487         Setup [] newSetups = new Setup[files.length];
488         for (int i = 0; i < newSetups.length; i++) {
489             File JavaDoc file = files[i];
490             newSetups[i] = new Setup(file, currentType);
491         }
492         Arrays.sort(newSetups, new SetupsComparator());
493
494         setups = newSetups;
495         navigationCombo.setModel(new DefaultComboBoxModel(setups));
496
497         if (setups.length == 0) {
498             String JavaDoc noContentLabel;
499             switch (currentType) {
500             case Setup.DIFFTYPE_LOCAL:
501                 noContentLabel = NbBundle.getMessage(DiffMainPanel.class, "MSG_DiffPanel_NoLocalChanges");
502                 break;
503             case Setup.DIFFTYPE_REMOTE:
504                 noContentLabel = NbBundle.getMessage(DiffMainPanel.class, "MSG_DiffPanel_NoRemoteChanges");
505                 break;
506             case Setup.DIFFTYPE_ALL:
507                 noContentLabel = NbBundle.getMessage(DiffMainPanel.class, "MSG_DiffPanel_NoAllChanges");
508                 break;
509             default:
510                 throw new IllegalStateException JavaDoc("Unknown DIFF type:" + currentType); // NOI18N
511
}
512             setups = null;
513             navigationCombo.setModel(new DefaultComboBoxModel(new Object JavaDoc [] { noContentLabel }));
514             navigationCombo.setEnabled(false);
515             navigationCombo.setPreferredSize(null);
516             Dimension dim = navigationCombo.getPreferredSize();
517             navigationCombo.setPreferredSize(new Dimension(dim.width + 1, dim.height));
518             removeDiffComponent();
519             diffView = new SourcesUnavailableComponent(noContentLabel);
520             add(diffView);
521             nextAction.setEnabled(false);
522             prevAction.setEnabled(false);
523             revalidate();
524             repaint();
525             executed();
526         } else {
527             navigationCombo.setEnabled(true);
528             navigationCombo.setPreferredSize(null);
529             Dimension dim = navigationCombo.getPreferredSize();
530             navigationCombo.setPreferredSize(new Dimension(dim.width + 1, dim.height));
531             setDiffIndex(0, 0);
532             dpt = new DiffPrepareTask(setups);
533             prepareTask = RequestProcessor.getDefault().post(dpt);
534         }
535     }
536     
537     private void onDiffTypeChanged() {
538         if (localToggle.isSelected()) {
539             if (currentType == Setup.DIFFTYPE_LOCAL) return;
540             currentType = Setup.DIFFTYPE_LOCAL;
541         } else if (remoteToggle.isSelected()) {
542             if (currentType == Setup.DIFFTYPE_REMOTE) return;
543             currentType = Setup.DIFFTYPE_REMOTE;
544         } else if (allToggle.isSelected()) {
545             if (currentType == Setup.DIFFTYPE_ALL) return;
546             currentType = Setup.DIFFTYPE_ALL;
547         }
548         refreshSetups();
549     }
550
551     /** This method is called from within the constructor to
552      * initialize the form.
553      * WARNING: Do NOT modify this code. The content of this method is
554      * always regenerated by the Form Editor.
555      */

556     // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
557
private void initComponents() {
558         controlsToolbar = new javax.swing.JToolBar JavaDoc();
559         allToggle = new javax.swing.JToggleButton JavaDoc();
560         localToggle = new javax.swing.JToggleButton JavaDoc();
561         remoteToggle = new javax.swing.JToggleButton JavaDoc();
562         navigationCombo = new javax.swing.JComboBox JavaDoc();
563         nextButton = new javax.swing.JButton JavaDoc();
564         prevButton = new javax.swing.JButton JavaDoc();
565         jPanel1 = new javax.swing.JPanel JavaDoc();
566         refreshButton = new javax.swing.JButton JavaDoc();
567         updateButton = new javax.swing.JButton JavaDoc();
568         commitButton = new javax.swing.JButton JavaDoc();
569
570         setLayout(new java.awt.BorderLayout JavaDoc());
571
572         controlsToolbar.setFloatable(false);
573         allToggle.setText(java.util.ResourceBundle.getBundle("org/netbeans/modules/versioning/system/cvss/ui/actions/diff/Bundle").getString("CTL_DiffPanel_All"));
574         allToggle.setToolTipText(java.util.ResourceBundle.getBundle("org/netbeans/modules/versioning/system/cvss/ui/actions/diff/Bundle").getString("CTL_DiffPanel_All_Tooltip"));
575         controlsToolbar.add(allToggle);
576
577         localToggle.setText(java.util.ResourceBundle.getBundle("org/netbeans/modules/versioning/system/cvss/ui/actions/diff/Bundle").getString("CTL_DiffPanel_Local"));
578         localToggle.setToolTipText(java.util.ResourceBundle.getBundle("org/netbeans/modules/versioning/system/cvss/ui/actions/diff/Bundle").getString("CTL_DiffPanel_Local_Tooltip"));
579         controlsToolbar.add(localToggle);
580
581         remoteToggle.setText(java.util.ResourceBundle.getBundle("org/netbeans/modules/versioning/system/cvss/ui/actions/diff/Bundle").getString("CTL_DiffPanel_Remote"));
582         remoteToggle.setToolTipText(java.util.ResourceBundle.getBundle("org/netbeans/modules/versioning/system/cvss/ui/actions/diff/Bundle").getString("CTL_DiffPanel_Remote_Tooltip"));
583         controlsToolbar.add(remoteToggle);
584
585         controlsToolbar.add(navigationCombo);
586
587         nextButton.setIcon(new javax.swing.ImageIcon JavaDoc(getClass().getResource("/org/netbeans/modules/versioning/system/cvss/resources/icons/diff-next.png")));
588         nextButton.setToolTipText(java.util.ResourceBundle.getBundle("org/netbeans/modules/versioning/system/cvss/ui/actions/diff/Bundle").getString("CTL_DiffPanel_Next_Tooltip"));
589         nextButton.setEnabled(false);
590         controlsToolbar.add(nextButton);
591
592         prevButton.setIcon(new javax.swing.ImageIcon JavaDoc(getClass().getResource("/org/netbeans/modules/versioning/system/cvss/resources/icons/diff-prev.png")));
593         prevButton.setToolTipText(java.util.ResourceBundle.getBundle("org/netbeans/modules/versioning/system/cvss/ui/actions/diff/Bundle").getString("CTL_DiffPanel_Prev_Tooltip"));
594         prevButton.setEnabled(false);
595         controlsToolbar.add(prevButton);
596
597         jPanel1.setMaximumSize(new java.awt.Dimension JavaDoc(15, 1));
598         jPanel1.setPreferredSize(new java.awt.Dimension JavaDoc(15, 1));
599         controlsToolbar.add(jPanel1);
600
601         refreshButton.setIcon(new javax.swing.ImageIcon JavaDoc(getClass().getResource("/org/netbeans/modules/versioning/system/cvss/resources/icons/refresh.png")));
602         refreshButton.setToolTipText(java.util.ResourceBundle.getBundle("org/netbeans/modules/versioning/system/cvss/ui/actions/diff/Bundle").getString("CTL_DiffPanel_Prev_Tooltip"));
603         controlsToolbar.add(refreshButton);
604
605         updateButton.setIcon(new javax.swing.ImageIcon JavaDoc(getClass().getResource("/org/netbeans/modules/versioning/system/cvss/resources/icons/update.png")));
606         updateButton.setToolTipText(java.util.ResourceBundle.getBundle("org/netbeans/modules/versioning/system/cvss/ui/actions/diff/Bundle").getString("CTL_DiffPanel_Prev_Tooltip"));
607         controlsToolbar.add(updateButton);
608
609         commitButton.setIcon(new javax.swing.ImageIcon JavaDoc(getClass().getResource("/org/netbeans/modules/versioning/system/cvss/resources/icons/commit.png")));
610         commitButton.setToolTipText(java.util.ResourceBundle.getBundle("org/netbeans/modules/versioning/system/cvss/ui/actions/diff/Bundle").getString("CTL_DiffPanel_Prev_Tooltip"));
611         controlsToolbar.add(commitButton);
612
613         add(controlsToolbar, java.awt.BorderLayout.NORTH);
614
615     }
616     // </editor-fold>//GEN-END:initComponents
617

618     // Variables declaration - do not modify//GEN-BEGIN:variables
619
private javax.swing.JToggleButton JavaDoc allToggle;
620     private javax.swing.JButton JavaDoc commitButton;
621     private javax.swing.JToolBar JavaDoc controlsToolbar;
622     private javax.swing.JPanel JavaDoc jPanel1;
623     private javax.swing.JToggleButton JavaDoc localToggle;
624     private javax.swing.JComboBox JavaDoc navigationCombo;
625     private javax.swing.JButton JavaDoc nextButton;
626     private javax.swing.JButton JavaDoc prevButton;
627     private javax.swing.JButton JavaDoc refreshButton;
628     private javax.swing.JToggleButton JavaDoc remoteToggle;
629     private javax.swing.JButton JavaDoc updateButton;
630     // End of variables declaration//GEN-END:variables
631

632     
633     private class DiffPrepareTask implements Runnable JavaDoc {
634         
635         private final Setup[] prepareSetups;
636
637         public DiffPrepareTask(Setup [] prepareSetups) {
638             this.prepareSetups = prepareSetups;
639         }
640
641         public void run() {
642             final Diff diff = Diff.getDefault();
643             try {
644                 for (int i = 0; i < prepareSetups.length; i++) {
645                     if (prepareSetups != setups) return;
646                     try {
647                         prepareSetups[i].initSources(group); // slow network I/O
648
final int fi = i;
649                         StreamSource ss1 = prepareSetups[fi].getFirstSource();
650                         StreamSource ss2 = prepareSetups[fi].getSecondSource();
651                         final DiffView view = diff.createDiff(ss1, ss2); // possibly executing slow external diff
652

653                         SwingUtilities.invokeLater(new Runnable JavaDoc() {
654                             public void run() {
655                                 prepareSetups[fi].setView(view);
656                                 if (prepareSetups != setups) {
657                                     return;
658                                 }
659                                 if (currentIndex == fi) {
660                                     setDiffIndex(fi, 0);
661                                 }
662                             }
663                         });
664                     } catch (IOException JavaDoc e) {
665                         ErrorManager.getDefault().notify(e);
666                     }
667                 }
668             } finally {
669                 executed();
670             }
671         }
672     }
673
674     private synchronized void executed() {
675         if (group != null) {
676             group.executed();
677         } else {
678             // to warn setGroup that DiffPrepareTask already finished
679
executed = true;
680         }
681     }
682
683     private static class SourcesUnavailableComponent extends JComponent {
684         
685         public SourcesUnavailableComponent(String JavaDoc message) {
686             JLabel label = new JLabel(message);
687             setLayout(new BorderLayout());
688             label.setHorizontalAlignment(JLabel.CENTER);
689             add(label, BorderLayout.CENTER);
690         }
691     }
692     
693     /**
694      * Hardcoded toolbar layout. It eliminates need
695      * for nested panels their look is hardly maintanable
696      * accross several look and feels
697      * (e.g. strange layouting panel borders on GTK+).
698      *
699      * <p>It sets authoritatively component height and takes
700      * "prefered" width from components itself.
701      *
702      */

703     private class ToolbarLayout implements LayoutManager {
704
705         /** Expected border height */
706         private int TOOLBAR_HEIGHT_ADJUSTMENT = 10;
707
708         private int TOOLBAR_SEPARATOR_MIN_WIDTH = 12;
709
710         /** Cached toolbar height */
711         private int toolbarHeight = -1;
712
713         /** Guard for above cache. */
714         private Dimension parentSize;
715
716         private Set adjusted = new HashSet();
717
718         public void removeLayoutComponent(Component comp) {
719         }
720
721         public void layoutContainer(Container parent) {
722             Rectangle [] sizes = layout(parent);
723             for (int i = 0; i < sizes.length; i++) {
724                 JComponent comp = (JComponent) parent.getComponent(i);
725                 if (comp.isVisible()) {
726                     comp.setBounds(sizes[i]);
727                 }
728             }
729         }
730
731         private Rectangle [] layout(Container parent) {
732             Dimension dim = DiffMainPanel.this.getSize();
733             Dimension max = parent.getSize();
734             int rowOffset = 0;
735             int maxHeigth = 0;
736
737             List JavaDoc sizes = new ArrayList();
738             int components = parent.getComponentCount();
739             int horizont = 0;
740             for (int i = 0; i < components; i++) {
741                 Rectangle rect = new Rectangle();
742                 JComponent comp = (JComponent) parent.getComponent(i);
743                 if (comp.isVisible()) {
744                     rect.setLocation(horizont, rowOffset);
745                     if (comp instanceof AbstractButton) {
746                         adjustToobarButton((AbstractButton)comp);
747                     } else {
748                         adjustToolbarComponentSize((JComponent)comp);
749                     }
750                     Dimension pref = comp.getPreferredSize();
751                     int width = pref.width;
752                     if (comp instanceof JSeparator && ((dim.height - dim.width) <= 0)) {
753                         width = Math.max(width, TOOLBAR_SEPARATOR_MIN_WIDTH);
754                     }
755     
756                     // in column layout use taller toolbar
757
int height = getToolbarHeight(dim) -1;
758                     maxHeigth = Math.max(maxHeigth, height);
759                     rect.setSize(width, height); // 1 verySoftBevel compensation
760
horizont += width;
761                     if (horizont > max.width) {
762                         rowOffset += maxHeigth + 2;
763                         horizont = 0;
764                         maxHeigth = 0;
765                     }
766                 }
767                 sizes.add(rect);
768             }
769             return (Rectangle[]) sizes.toArray(new Rectangle[sizes.size()]);
770         }
771         
772         public void addLayoutComponent(String JavaDoc name, Component comp) {
773         }
774
775         public Dimension minimumLayoutSize(Container parent) {
776
777             // in column layout use taller toolbar
778
Dimension dim = DiffMainPanel.this.getSize();
779             int height = getToolbarHeight(dim);
780
781             int components = parent.getComponentCount();
782             int horizont = 0;
783             for (int i = 0; i<components; i++) {
784                 Component comp = parent.getComponent(i);
785                 if (comp.isVisible() == false) continue;
786                 if (comp instanceof AbstractButton) {
787                     adjustToobarButton((AbstractButton)comp);
788                 } else {
789                     adjustToolbarComponentSize((JComponent)comp);
790                 }
791                 Dimension pref = comp.getPreferredSize();
792                 int width = pref.width;
793                 if (comp instanceof JSeparator && ((dim.height - dim.width) <= 0)) {
794                     width = Math.max(width, TOOLBAR_SEPARATOR_MIN_WIDTH);
795                 }
796                 horizont += width;
797             }
798
799             return new Dimension(horizont, height);
800         }
801
802         public Dimension preferredLayoutSize(Container parent) {
803             Rectangle [] bounds = layout(parent);
804             Rectangle union = new Rectangle();
805             for (int i = 0; i < bounds.length; i++) {
806                 union.add(bounds[i]);
807             }
808             return new Dimension(union.width, union.height);
809         }
810
811         /**
812          * Computes vertical toolbar components height that can used for layout manager hinting.
813          * @return size based on font size and expected border.
814          */

815         private int getToolbarHeight(Dimension parent) {
816
817             if (parentSize == null || (parentSize.equals(parent) == false)) {
818                 parentSize = parent;
819                 toolbarHeight = -1;
820             }
821
822             if (toolbarHeight == -1) {
823                 BufferedImage JavaDoc image = new BufferedImage JavaDoc(1,1,BufferedImage.TYPE_BYTE_GRAY);
824                 Graphics2D g = image.createGraphics();
825                 UIDefaults def = UIManager.getLookAndFeelDefaults();
826
827                 int height = 0;
828                 String JavaDoc[] fonts = {"Label.font", "Button.font", "ToggleButton.font"}; // NOI18N
829
for (int i=0; i<fonts.length; i++) {
830                     Font f = def.getFont(fonts[i]);
831                     FontMetrics fm = g.getFontMetrics(f);
832                     height = Math.max(height, fm.getHeight());
833                 }
834                 toolbarHeight = height + TOOLBAR_HEIGHT_ADJUSTMENT;
835             }
836
837             return toolbarHeight;
838         }
839
840
841         /** Toolbar controls must be smaller and should be transparent*/
842         private void adjustToobarButton(final AbstractButton button) {
843
844             if (adjusted.contains(button)) return;
845
846             // workaround for Ocean L&F clutter - toolbars use gradient.
847
// To make the gradient visible under buttons the content area must not
848
// be filled. To support rollover it must be temporarily filled
849
if (button instanceof JToggleButton == false) {
850                 button.setContentAreaFilled(false);
851                 button.setMargin(new Insets(0, 3, 0, 3));
852                 button.setBorderPainted(false);
853                 button.addMouseListener(new MouseAdapter() {
854                     public void mouseEntered(MouseEvent e) {
855                         button.setContentAreaFilled(true);
856                         button.setBorderPainted(true);
857                     }
858
859                     public void mouseExited(MouseEvent e) {
860                         button.setContentAreaFilled(false);
861                         button.setBorderPainted(false);
862                     }
863                 });
864             }
865
866             adjustToolbarComponentSize(button);
867         }
868
869         private void adjustToolbarComponentSize(JComponent button) {
870
871             if (adjusted.contains(button)) return;
872
873             // as we cannot get the button small enough using the margin and border...
874
if (button.getBorder() instanceof CompoundBorder JavaDoc) { // from BasicLookAndFeel
875
Dimension pref = button.getPreferredSize();
876
877                 // XXX #41827 workaround w2k, that adds eclipsis (...) instead of actual text
878
if ("Windows".equals(UIManager.getLookAndFeel().getID())) { // NOI18N
879
pref.width += 9;
880                 }
881                 button.setPreferredSize(pref);
882             }
883
884             adjusted.add(button);
885         }
886     }
887
888     private static class SetupsComparator extends Utils.ByImportanceComparator {
889
890         private FileStatusCache cache;
891
892         public SetupsComparator() {
893             cache = CvsVersioningSystem.getInstance().getStatusCache();
894         }
895
896         public int compare(Object JavaDoc o1, Object JavaDoc o2) {
897             File JavaDoc file1 = ((Setup) o1).getBaseFile();
898             File JavaDoc file2 = ((Setup) o2).getBaseFile();
899             int cmp = super.compare(cache.getStatus(file1), cache.getStatus(file2));
900             if (cmp == 0) {
901                 return file1.getName().compareToIgnoreCase(file2.getName());
902             }
903             return cmp;
904         }
905     }
906
907     private class RefreshViewTask implements Runnable JavaDoc {
908         public void run() {
909             SwingUtilities.invokeLater(new Runnable JavaDoc() {
910                 public void run() {
911                     refreshSetups();
912                 }
913             });
914         }
915     }
916 }
917
Popular Tags