KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > subversion > ui > browser > Browser


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.browser;
20
21 import java.beans.PropertyChangeEvent JavaDoc;
22 import java.beans.PropertyChangeListener JavaDoc;
23 import java.beans.PropertyVetoException JavaDoc;
24 import java.beans.VetoableChangeListener JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.Collections JavaDoc;
28 import java.util.List JavaDoc;
29 import javax.swing.Action JavaDoc;
30 import javax.swing.JPanel JavaDoc;
31 import org.netbeans.modules.subversion.RepositoryFile;
32 import org.netbeans.modules.subversion.Subversion;
33 import org.netbeans.modules.subversion.client.ExceptionHandler;
34 import org.netbeans.modules.subversion.client.SvnClient;
35 import org.netbeans.modules.subversion.client.SvnProgressSupport;
36 import org.openide.ErrorManager;
37 import org.openide.explorer.ExplorerManager;
38 import org.openide.nodes.Node;
39 import org.tigris.subversion.svnclientadapter.ISVNDirEntry;
40 import org.tigris.subversion.svnclientadapter.SVNClientException;
41 import org.tigris.subversion.svnclientadapter.SVNNodeKind;
42
43 /**
44  * Handles the UI for repository browsing.
45  *
46  * @author Tomas Stupka
47  */

48 public class Browser implements VetoableChangeListener JavaDoc, BrowserClient {
49         
50     
51     public final static int BROWSER_SHOW_FILES = 1;
52     public final static int BROWSER_SINGLE_SELECTION_ONLY = 2;
53     public final static int BROWSER_FILES_SELECTION_ONLY = 4;
54     public final static int BROWSER_FOLDERS_SELECTION_ONLY = 8;
55     public final static int BROWSER_SELECT_ANYTHING = BROWSER_FOLDERS_SELECTION_ONLY | BROWSER_FILES_SELECTION_ONLY;
56
57     private final int mode;
58     
59     private static final RepositoryFile[] EMPTY_ROOT = new RepositoryFile[0];
60     private static final Action JavaDoc[] EMPTY_ACTIONS = new Action JavaDoc[0];
61     
62     private final BrowserPanel panel;
63             
64     private RepositoryFile repositoryRoot;
65     private Action JavaDoc[] nodeActions;
66
67     private SvnProgressSupport support;
68
69     /**
70      * Creates a new instance
71      *
72      * @param title the browsers window title
73      * @param showFiles
74      * @param singleSelectionOnly
75      * @param fileSelectionOnly
76      * @param repositoryRoot the RepositoryFile representing the repository root
77      * @param select an array of RepositoryFile-s representing the items which has to be selected
78      * @param nodeActions an array of actions from which the context menu on the tree items will be created
79      *
80      */

81     public Browser(String JavaDoc title, int mode, RepositoryFile repositoryRoot, RepositoryFile[] select, BrowserAction[] nodeActions) {
82         this.mode = mode;
83         
84         panel = new BrowserPanel(title,
85                                  org.openide.util.NbBundle.getMessage(Browser.class, "ACSN_RepositoryTree"), // NOI18N
86
org.openide.util.NbBundle.getMessage(Browser.class, "ACSD_RepositoryTree"), // NOI18N
87
(mode & BROWSER_SINGLE_SELECTION_ONLY) == BROWSER_SINGLE_SELECTION_ONLY);
88         
89         panel.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(RepositoryPathNode.class, "CTL_Browser_Prompt")); // NOI18N
90
getExplorerManager().addVetoableChangeListener(this);
91         
92         if(nodeActions!=null) {
93             this.nodeActions = nodeActions;
94             panel.setActions(nodeActions);
95             for (int i = 0; i < nodeActions.length; i++) {
96                 nodeActions[i].setBrowser(this);
97             }
98         } else {
99             this.nodeActions = EMPTY_ACTIONS;
100         }
101         this.repositoryRoot = repositoryRoot;
102         
103         RepositoryPathNode rootNode = RepositoryPathNode.createRepositoryPathNode(this, repositoryRoot);
104         Node[] selectedNodes = getSelectedNodes(rootNode, repositoryRoot, select);
105         getExplorerManager().setRootContext(rootNode);
106         
107         if(selectedNodes==null) {
108             selectedNodes = new Node[] {};
109         }
110         
111         try {
112             getExplorerManager().setSelectedNodes(selectedNodes);
113             for (int i = 0; i < selectedNodes.length; i++) {
114                 getExplorerManager().setExploredContext(selectedNodes[i]);
115             }
116         } catch (PropertyVetoException JavaDoc ex) {
117             ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
118         }
119         
120     }
121
122     private Node[] getSelectedNodes(RepositoryPathNode rootNode, RepositoryFile repositoryRoot, RepositoryFile[] select) {
123         if(select==null || select.length <= 0) {
124             return null;
125         }
126         Node segmentParentNode = null;
127         List JavaDoc<Node> nodesToSelect = new ArrayList JavaDoc<Node>(select.length);
128
129         for (int i = 0; i < select.length; i++) {
130             String JavaDoc[] segments = select[i].getPathSegments();
131             segmentParentNode = rootNode;
132             RepositoryFile segmentFile = repositoryRoot;
133             for (int j = 0; j < segments.length; j++) {
134                 segmentFile = segmentFile.appendPath(segments[j]);
135                 RepositoryPathNode segmentNode = RepositoryPathNode.createRepositoryPathNode(this, segmentFile);
136                 segmentParentNode.getChildren().add(new Node[] {segmentNode});
137                 segmentParentNode = segmentNode;
138             }
139             nodesToSelect.add(segmentParentNode);
140         }
141         return nodesToSelect.toArray(new Node[nodesToSelect.size()]);
142     }
143
144     /**
145      * Cancels all running tasks
146      */

147     public void cancel() {
148         Node rootNode = getExplorerManager().getRootContext();
149         if(rootNode != null) {
150             getExplorerManager().setRootContext(Node.EMPTY);
151             try {
152                 rootNode.destroy();
153                 if(support != null) {
154                     support.cancel();
155                 }
156             } catch (IOException JavaDoc ex) {
157                 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex); // should not happen
158
}
159         }
160     }
161     
162     public List JavaDoc listRepositoryPath(final RepositoryPathNode.RepositoryPathEntry entry, SvnProgressSupport support) throws SVNClientException {
163         List JavaDoc<RepositoryPathNode.RepositoryPathEntry> ret;
164         try {
165
166             this.support = support;
167
168             if(entry.getSvnNodeKind().equals(SVNNodeKind.FILE)) {
169                 return Collections.EMPTY_LIST; // nothing to do...
170
}
171
172             SvnClient client = Subversion.getInstance().getClient(this.repositoryRoot.getRepositoryUrl(), support);
173             if(support.isCanceled()) {
174                 return null;
175             }
176
177             ret = new ArrayList JavaDoc<RepositoryPathNode.RepositoryPathEntry>();
178
179             ISVNDirEntry[] dirEntries = client.getList(
180                                             entry.getRepositoryFile().getFileUrl(),
181                                             entry.getRepositoryFile().getRevision(),
182                                             false
183                                         );
184
185             if(dirEntries == null || dirEntries.length == 0) {
186                 return Collections.EMPTY_LIST; // nothing to do...
187
}
188                         
189             for (int i = 0; i < dirEntries.length; i++) {
190                 if(support.isCanceled()) {
191                     return null;
192                 }
193
194                 ISVNDirEntry dirEntry = dirEntries[i];
195                 if( dirEntry.getNodeKind()==SVNNodeKind.DIR || // directory or
196
(dirEntry.getNodeKind()==SVNNodeKind.FILE && // (file and show_files_allowed)
197
((mode & BROWSER_SHOW_FILES) == BROWSER_SHOW_FILES)) )
198                 {
199                     RepositoryFile repositoryFile = entry.getRepositoryFile();
200                     RepositoryPathNode.RepositoryPathEntry e =
201                             new RepositoryPathNode.RepositoryPathEntry(
202                             repositoryFile.appendPath(dirEntry.getPath()),
203                             dirEntry.getNodeKind(),
204                             dirEntry.getLastChangedRevision(),
205                             dirEntry.getLastChangedDate(),
206                             dirEntry.getLastCommitAuthor());
207                     ret.add(e);
208                 }
209             }
210             
211         } catch (SVNClientException ex) {
212             if(ExceptionHandler.isWrongURLInRevision(ex.getMessage())) {
213                 // is not a folder in the repository
214
return null;
215             } else {
216                 support.annotate(ex);
217                 throw ex;
218             }
219         }
220         finally {
221             this.support = null;
222         }
223
224         return ret;
225     }
226     
227     public JPanel JavaDoc getBrowserPanel() {
228         return panel;
229     }
230     
231     public Node[] getSelectedNodes() {
232         return getExplorerManager().getSelectedNodes();
233     }
234
235     public RepositoryFile[] getSelectedFiles() {
236         Node[] nodes = (Node[]) getExplorerManager().getSelectedNodes();
237         
238         if(nodes.length == 0) {
239             return EMPTY_ROOT;
240         }
241         
242         RepositoryFile[] ret = new RepositoryFile[nodes.length];
243         for (int i = 0; i < nodes.length; i++) {
244             ret[i] = ((RepositoryPathNode) nodes[i]).getEntry().getRepositoryFile();
245         }
246         return ret;
247     }
248     
249     private boolean keepWarning = false;
250     private boolean initialSelection = true;
251     
252     public void vetoableChange(PropertyChangeEvent JavaDoc evt) throws PropertyVetoException JavaDoc {
253         if (ExplorerManager.PROP_SELECTED_NODES.equals(evt.getPropertyName())) {
254            
255             boolean initialSelectionDone = !initialSelection;
256             initialSelection = false;
257             
258             if(!keepWarning) {
259                 panel.warning(null);
260             }
261             keepWarning = false;
262             
263             Node[] newSelection = (Node[]) evt.getNewValue();
264             Node[] oldSelection = (Node[]) evt.getOldValue();
265             if(newSelection == null || newSelection.length == 0) {
266                 return;
267             }
268
269             // RULE: don't select the repository node
270
// if(containsRootNode(newSelection)) {
271
// throw new PropertyVetoException("", evt); // NOI18N
272
// }
273

274             if((mode & BROWSER_FILES_SELECTION_ONLY) == BROWSER_FILES_SELECTION_ONLY) { // file selection only
275
if(checkForNodeType(newSelection, SVNNodeKind.DIR)) {
276                     panel.warning(org.openide.util.NbBundle.getMessage(Browser.class, "LBL_Warning_FileSelectionOnly")); // NOI18N
277
if(initialSelectionDone) keepWarning = true;
278                     throw new PropertyVetoException JavaDoc("", evt); // NOI18N
279
}
280             }
281             
282             if((mode & BROWSER_FOLDERS_SELECTION_ONLY) == BROWSER_FOLDERS_SELECTION_ONLY) { // folder selection only
283
if(checkForNodeType(newSelection, SVNNodeKind.FILE)) {
284                     panel.warning(org.openide.util.NbBundle.getMessage(Browser.class, "LBL_Warning_FolderSelectionOnly")); // NOI18N
285
if(initialSelectionDone) keepWarning = true;
286                     throw new PropertyVetoException JavaDoc("", evt); // NOI18N
287
}
288             }
289             
290             
291             // RULE: don't select nodes on a different level as the already selected
292
if(oldSelection.length == 0 && newSelection.length == 1) {
293                 // it is first node selected ->
294
// -> there is nothig to check
295
return;
296             }
297                                     
298             if(oldSelection.length != 0 && areDisjunct(oldSelection, newSelection)) {
299                 // as if the first node would be selected ->
300
// -> there is nothig to check
301
return;
302             }
303
304             Node selectedNode = null;
305             if(oldSelection.length > 0) {
306                 // we anticipate that nothing went wrong and
307
// all nodes in the old selection are at the same level
308
selectedNode = oldSelection[0];
309             } else {
310                 selectedNode = newSelection[0];
311             }
312             if(!selectionIsAtLevel(newSelection, getNodeLevel(selectedNode))) {
313                 panel.warning(org.openide.util.NbBundle.getMessage(Browser.class, "LBL_Warning_NoMultiSelection")); // NOI18N
314
if(initialSelectionDone) keepWarning = true;
315                 throw new PropertyVetoException JavaDoc("", evt); // NOI18N
316
}
317         }
318     }
319     
320     private boolean checkForNodeType(Node[] newSelection, SVNNodeKind nodeKind) {
321         for (int i = 0; i < newSelection.length; i++) {
322             if(newSelection[i] instanceof RepositoryPathNode) {
323                 RepositoryPathNode node = (RepositoryPathNode) newSelection[i];
324                 if(node.getEntry().getSvnNodeKind() == nodeKind) {
325                     return true;
326                 }
327             }
328         }
329         return false;
330     }
331    
332     
333     private boolean selectionIsAtLevel(Node[] newSelection, int level) {
334         for (int i = 0; i < newSelection.length; i++) {
335              if (getNodeLevel(newSelection[i]) != level) {
336                 return false;
337              }
338         }
339         return true;
340     }
341     
342     private boolean areDisjunct(Node[] oldSelection, Node[] newSelection) {
343         for (int i = 0; i < oldSelection.length; i++) {
344             if(isInArray(oldSelection[i], newSelection)) {
345                 return false;
346             }
347         }
348         return true;
349     }
350     
351     private int getNodeLevel(Node node) {
352         int level = 0;
353         while(node!=null) {
354             node = node.getParentNode();
355             level++;
356         }
357         return level;
358     }
359     
360     private boolean isInArray(Node node, Node[] nodeArray) {
361         for (int i = 0; i < nodeArray.length; i++) {
362             if(node==nodeArray[i]) {
363                 return true;
364             }
365         }
366         return false;
367     }
368     
369     public void addPropertyChangeListener(PropertyChangeListener JavaDoc listener) {
370         getExplorerManager().addPropertyChangeListener(listener);
371     }
372     
373     public void removePropertyChangeListener(PropertyChangeListener JavaDoc listener) {
374         getExplorerManager().removePropertyChangeListener(listener);
375     }
376     
377     ExplorerManager getExplorerManager() {
378         return panel.getExplorerManager();
379     }
380
381     public Action JavaDoc[] getActions() {
382         return nodeActions;
383     }
384
385     void setSelectedNodes(Node[] selection) throws PropertyVetoException JavaDoc {
386         getExplorerManager().setSelectedNodes(selection);
387     }
388 }
389
Popular Tags