KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > subversion > ui > history > DiffResultsView


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 package org.netbeans.modules.subversion.ui.history;
20
21 import org.openide.util.RequestProcessor;
22 import org.openide.util.NbBundle;
23 import org.openide.util.Cancellable;
24 import org.openide.explorer.ExplorerManager;
25 import org.openide.nodes.Node;
26 import org.openide.ErrorManager;
27 import org.openide.windows.TopComponent;
28 import org.netbeans.api.diff.DiffView;
29 import org.netbeans.api.diff.Diff;
30 import org.netbeans.modules.versioning.util.NoContentPanel;
31 import org.netbeans.modules.subversion.ui.diff.DiffStreamSource;
32 import org.netbeans.modules.subversion.ui.diff.DiffSetupSource;
33 import javax.swing.event.AncestorListener JavaDoc;
34 import javax.swing.event.AncestorEvent JavaDoc;
35 import javax.swing.*;
36 import java.beans.PropertyChangeListener JavaDoc;
37 import java.beans.PropertyChangeEvent JavaDoc;
38 import java.util.*;
39 import java.awt.Component JavaDoc;
40 import java.io.File JavaDoc;
41 import java.io.IOException JavaDoc;
42
43 /**
44  * Shows Search History results in a table with Diff pane below it.
45  *
46  * @author Maros Sandor
47  */

48 class DiffResultsView implements AncestorListener JavaDoc, PropertyChangeListener JavaDoc, DiffSetupSource {
49
50     private final SearchHistoryPanel parent;
51
52     private DiffTreeTable treeView;
53     private JSplitPane diffView;
54     
55     private ShowDiffTask currentTask;
56     private RequestProcessor.Task currentShowDiffTask;
57     
58     private DiffView currentDiff;
59     private int currentDifferenceIndex;
60     private int currentIndex;
61     private boolean dividerSet;
62     private List<RepositoryRevision> results;
63
64     public DiffResultsView(SearchHistoryPanel parent, List<RepositoryRevision> results) {
65         this.parent = parent;
66         this.results = results;
67         treeView = new DiffTreeTable(parent);
68         treeView.setResults(results);
69         treeView.addAncestorListener(this);
70
71         diffView = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
72         diffView.setTopComponent(treeView);
73         setBottomComponent(new NoContentPanel(NbBundle.getMessage(DiffResultsView.class, "MSG_DiffPanel_NoRevisions"))); // NOI18N
74
}
75
76     public void ancestorAdded(AncestorEvent JavaDoc event) {
77         ExplorerManager em = ExplorerManager.find(treeView);
78         em.addPropertyChangeListener(this);
79         if (!dividerSet) {
80             SwingUtilities.invokeLater(new Runnable JavaDoc() {
81                 public void run() {
82                     dividerSet = true;
83                     diffView.setDividerLocation(0.33);
84                 }
85             });
86         }
87     }
88
89     public void ancestorMoved(AncestorEvent JavaDoc event) {
90     }
91
92     public void ancestorRemoved(AncestorEvent JavaDoc event) {
93         ExplorerManager em = ExplorerManager.find(treeView);
94         em.removePropertyChangeListener(this);
95         cancelBackgroundTasks();
96     }
97
98     public void propertyChange(PropertyChangeEvent JavaDoc evt) {
99         if (ExplorerManager.PROP_SELECTED_NODES.equals(evt.getPropertyName())) {
100             final Node [] nodes = (Node[]) evt.getNewValue();
101             currentDifferenceIndex = 0;
102             if (nodes.length == 0) {
103                 showDiffError(NbBundle.getMessage(DiffResultsView.class, "MSG_DiffPanel_NoRevisions")); // NOI18N
104
parent.refreshComponents(false);
105                 return;
106             }
107             else if (nodes.length > 2) {
108                 showDiffError(NbBundle.getMessage(DiffResultsView.class, "MSG_DiffPanel_TooManyRevisions")); // NOI18N
109
parent.refreshComponents(false);
110                 return;
111             }
112
113             // invoked asynchronously becase treeView.getSelection() may not be ready yet
114
Runnable JavaDoc runnable = new Runnable JavaDoc() {
115                 public void run() {
116                     RepositoryRevision container1 = (RepositoryRevision) nodes[0].getLookup().lookup(RepositoryRevision.class);
117                     RepositoryRevision.Event r1 = (RepositoryRevision.Event) nodes[0].getLookup().lookup(RepositoryRevision.Event.class);
118                     try {
119                         currentIndex = treeView.getSelection()[0];
120                         if (nodes.length == 1) {
121                             if (container1 != null) {
122                                 showContainerDiff(container1, onSelectionshowLastDifference);
123                             }
124                             else if (r1 != null) {
125                                 showRevisionDiff(r1, onSelectionshowLastDifference);
126                             }
127                         } else if (nodes.length == 2) {
128                             RepositoryRevision.Event r2 = (RepositoryRevision.Event) nodes[1].getLookup().lookup(RepositoryRevision.Event.class);
129                             if (r2.getFile() == null || !r2.getFile().equals(r1.getFile())) {
130                                 throw new Exception JavaDoc();
131                             }
132                             long revision2 = r1.getLogInfoHeader().getLog().getRevision().getNumber();
133                             long revision1 = r2.getLogInfoHeader().getLog().getRevision().getNumber();
134                             showDiff(r1, Long.toString(revision1), Long.toString(revision2), false);
135                         }
136                     } catch (Exception JavaDoc e) {
137                         showDiffError(NbBundle.getMessage(DiffResultsView.class, "MSG_DiffPanel_IllegalSelection")); // NOI18N
138
parent.refreshComponents(false);
139                         return;
140                     }
141
142                 }
143             };
144             SwingUtilities.invokeLater(runnable);
145         }
146     }
147
148     public Collection getSetups() {
149         Node [] nodes = TopComponent.getRegistry().getActivatedNodes();
150         if (nodes.length == 0) {
151             return parent.getSetups(results.toArray(new RepositoryRevision[results.size()]), new RepositoryRevision.Event[0]);
152         }
153         
154         Set<RepositoryRevision.Event> events = new HashSet<RepositoryRevision.Event>();
155         Set<RepositoryRevision> revisions = new HashSet<RepositoryRevision>();
156         for (Node n : nodes) {
157             RevisionNode node = (RevisionNode) n;
158             if (node.getEvent() != null) {
159                 events.add(node.getEvent());
160             } else {
161                 revisions.add(node.getContainer());
162             }
163         }
164         return parent.getSetups(revisions.toArray(new RepositoryRevision[revisions.size()]), events.toArray(new RepositoryRevision.Event[events.size()]));
165     }
166
167     public String JavaDoc getSetupDisplayName() {
168         return null;
169     }
170
171     private void showDiffError(String JavaDoc s) {
172         setBottomComponent(new NoContentPanel(s));
173     }
174
175     private void setBottomComponent(Component component) {
176         int dl = diffView.getDividerLocation();
177         diffView.setBottomComponent(component);
178         diffView.setDividerLocation(dl);
179     }
180
181     private void showDiff(RepositoryRevision.Event header, String JavaDoc revision1, String JavaDoc revision2, boolean showLastDifference) {
182         synchronized(this) {
183             cancelBackgroundTasks();
184             currentTask = new ShowDiffTask(header, revision1, revision2, showLastDifference);
185             currentShowDiffTask = RequestProcessor.getDefault().create(currentTask);
186             currentShowDiffTask.schedule(0);
187         }
188     }
189
190     private synchronized void cancelBackgroundTasks() {
191         if (currentShowDiffTask != null && !currentShowDiffTask.isFinished()) {
192             currentShowDiffTask.cancel(); // it almost always late it's enqueued, so:
193
currentTask.cancel();
194         }
195     }
196
197     private boolean onSelectionshowLastDifference;
198
199     private void setDiffIndex(int idx, boolean showLastDifference) {
200         currentIndex = idx;
201         onSelectionshowLastDifference = showLastDifference;
202         treeView.setSelection(idx);
203     }
204
205     private void showRevisionDiff(RepositoryRevision.Event rev, boolean showLastDifference) {
206         if (rev.getFile() == null) return;
207         long revision2 = rev.getLogInfoHeader().getLog().getRevision().getNumber();
208         long revision1 = revision2 - 1;
209         showDiff(rev, Long.toString(revision1), Long.toString(revision2), showLastDifference);
210     }
211
212     private void showContainerDiff(RepositoryRevision container, boolean showLastDifference) {
213         List<RepositoryRevision.Event> revs = container.getEvents();
214         
215         RepositoryRevision.Event newest = null;
216         //try to get the root
217
File JavaDoc[] roots = parent.getRoots();
218         for(File JavaDoc root : roots) {
219             for(RepositoryRevision.Event evt : revs) {
220                 if(root.equals(evt.getFile())) {
221                     newest = evt;
222                 }
223             }
224         }
225         if(newest == null) {
226             newest = revs.get(0);
227         }
228         if (newest.getFile() == null) return;
229         long rev = newest.getLogInfoHeader().getLog().getRevision().getNumber();
230         showDiff(newest, Long.toString(rev - 1), Long.toString(rev), showLastDifference);
231     }
232     
233     void onNextButton() {
234         if (currentDiff != null) {
235             if (++currentDifferenceIndex >= currentDiff.getDifferenceCount()) {
236                 if (++currentIndex >= treeView.getRowCount()) currentIndex = 0;
237                 setDiffIndex(currentIndex, false);
238             } else {
239                 currentDiff.setCurrentDifference(currentDifferenceIndex);
240             }
241         } else {
242             if (++currentIndex >= treeView.getRowCount()) currentIndex = 0;
243             setDiffIndex(currentIndex, false);
244         }
245     }
246
247     void onPrevButton() {
248         if (currentDiff != null) {
249             if (--currentDifferenceIndex < 0) {
250                 if (--currentIndex < 0) currentIndex = treeView.getRowCount() - 1;
251                 setDiffIndex(currentIndex, true);
252             } else {
253                 currentDiff.setCurrentDifference(currentDifferenceIndex);
254             }
255         } else {
256             if (--currentIndex < 0) currentIndex = treeView.getRowCount() - 1;
257             setDiffIndex(currentIndex, true);
258         }
259     }
260
261     boolean isNextEnabled() {
262         if (currentDiff != null) {
263             return currentIndex < treeView.getRowCount() - 1 || currentDifferenceIndex < currentDiff.getDifferenceCount() - 1;
264         } else {
265             return false;
266         }
267     }
268
269     boolean isPrevEnabled() {
270         return currentIndex > 0 || currentDifferenceIndex > 0;
271     }
272     
273     /**
274      * Selects given revision in the view as if done by the user.
275      *
276      * @param revision revision to select
277      */

278     void select(RepositoryRevision.Event revision) {
279         treeView.requestFocusInWindow();
280         treeView.setSelection(revision);
281     }
282
283     void select(RepositoryRevision container) {
284         treeView.requestFocusInWindow();
285         treeView.setSelection(container);
286     }
287
288     private class ShowDiffTask implements Runnable JavaDoc, Cancellable {
289         
290         private final RepositoryRevision.Event header;
291         private final String JavaDoc revision1;
292         private final String JavaDoc revision2;
293         private boolean showLastDifference;
294         private volatile boolean cancelled;
295         private Thread JavaDoc thread;
296
297         public ShowDiffTask(RepositoryRevision.Event header, String JavaDoc revision1, String JavaDoc revision2, boolean showLastDifference) {
298             this.header = header;
299             this.revision1 = revision1;
300             this.revision2 = revision2;
301             this.showLastDifference = showLastDifference;
302         }
303
304         public void run() {
305             thread = Thread.currentThread();
306             final Diff diff = Diff.getDefault();
307             final DiffStreamSource s1 = new DiffStreamSource(header.getFile(), revision1, revision1);
308             final DiffStreamSource s2 = new DiffStreamSource(header.getFile(), revision2, revision2);
309
310             // it's enqueued at ClientRuntime queue and does not return until previous request handled
311
s1.getMIMEType(); // triggers s1.init()
312
if (cancelled) {
313                 return;
314             }
315
316             s2.getMIMEType(); // triggers s2.init()
317
if (cancelled) {
318                 return;
319             }
320
321             if (currentTask != this) return;
322
323             SwingUtilities.invokeLater(new Runnable JavaDoc() {
324                 public void run() {
325                     try {
326                         if (cancelled) {
327                             return;
328                         }
329                         final DiffView view = diff.createDiff(s1, s2);
330                         if (currentTask == ShowDiffTask.this) {
331                             currentDiff = view;
332                             setBottomComponent(currentDiff.getComponent());
333                             if (currentDiff.getDifferenceCount() > 0) {
334                                 currentDifferenceIndex = showLastDifference ? currentDiff.getDifferenceCount() - 1 : 0;
335                                 currentDiff.setCurrentDifference(currentDifferenceIndex);
336                             }
337                             parent.refreshComponents(false);
338                         }
339                     } catch (IOException JavaDoc e) {
340                         ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
341                     }
342                 }
343             });
344         }
345
346         public boolean cancel() {
347             cancelled = true;
348             if (thread != null) {
349                 thread.interrupt();
350             }
351             return true;
352         }
353     }
354     
355     public JComponent getComponent() {
356         return diffView;
357     }
358 }
359
360
361
Popular Tags