1 19 package org.netbeans.modules.subversion.ui.browser; 20 21 import java.beans.PropertyChangeEvent ; 22 import java.beans.PropertyChangeListener ; 23 import java.beans.PropertyVetoException ; 24 import java.beans.VetoableChangeListener ; 25 import java.io.IOException ; 26 import java.util.ArrayList ; 27 import java.util.Collections ; 28 import java.util.List ; 29 import javax.swing.Action ; 30 import javax.swing.JPanel ; 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 48 public class Browser implements VetoableChangeListener , 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 [] EMPTY_ACTIONS = new Action [0]; 61 62 private final BrowserPanel panel; 63 64 private RepositoryFile repositoryRoot; 65 private Action [] nodeActions; 66 67 private SvnProgressSupport support; 68 69 81 public Browser(String 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"), org.openide.util.NbBundle.getMessage(Browser.class, "ACSD_RepositoryTree"), (mode & BROWSER_SINGLE_SELECTION_ONLY) == BROWSER_SINGLE_SELECTION_ONLY); 88 89 panel.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(RepositoryPathNode.class, "CTL_Browser_Prompt")); 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 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 <Node> nodesToSelect = new ArrayList <Node>(select.length); 128 129 for (int i = 0; i < select.length; i++) { 130 String [] 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 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 ex) { 157 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex); } 159 } 160 } 161 162 public List listRepositoryPath(final RepositoryPathNode.RepositoryPathEntry entry, SvnProgressSupport support) throws SVNClientException { 163 List <RepositoryPathNode.RepositoryPathEntry> ret; 164 try { 165 166 this.support = support; 167 168 if(entry.getSvnNodeKind().equals(SVNNodeKind.FILE)) { 169 return Collections.EMPTY_LIST; } 171 172 SvnClient client = Subversion.getInstance().getClient(this.repositoryRoot.getRepositoryUrl(), support); 173 if(support.isCanceled()) { 174 return null; 175 } 176 177 ret = new ArrayList <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; } 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 || (dirEntry.getNodeKind()==SVNNodeKind.FILE && ((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 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 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 evt) throws PropertyVetoException { 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 274 if((mode & BROWSER_FILES_SELECTION_ONLY) == BROWSER_FILES_SELECTION_ONLY) { if(checkForNodeType(newSelection, SVNNodeKind.DIR)) { 276 panel.warning(org.openide.util.NbBundle.getMessage(Browser.class, "LBL_Warning_FileSelectionOnly")); if(initialSelectionDone) keepWarning = true; 278 throw new PropertyVetoException ("", evt); } 280 } 281 282 if((mode & BROWSER_FOLDERS_SELECTION_ONLY) == BROWSER_FOLDERS_SELECTION_ONLY) { if(checkForNodeType(newSelection, SVNNodeKind.FILE)) { 284 panel.warning(org.openide.util.NbBundle.getMessage(Browser.class, "LBL_Warning_FolderSelectionOnly")); if(initialSelectionDone) keepWarning = true; 286 throw new PropertyVetoException ("", evt); } 288 } 289 290 291 if(oldSelection.length == 0 && newSelection.length == 1) { 293 return; 296 } 297 298 if(oldSelection.length != 0 && areDisjunct(oldSelection, newSelection)) { 299 return; 302 } 303 304 Node selectedNode = null; 305 if(oldSelection.length > 0) { 306 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")); if(initialSelectionDone) keepWarning = true; 315 throw new PropertyVetoException ("", evt); } 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 listener) { 370 getExplorerManager().addPropertyChangeListener(listener); 371 } 372 373 public void removePropertyChangeListener(PropertyChangeListener listener) { 374 getExplorerManager().removePropertyChangeListener(listener); 375 } 376 377 ExplorerManager getExplorerManager() { 378 return panel.getExplorerManager(); 379 } 380 381 public Action [] getActions() { 382 return nodeActions; 383 } 384 385 void setSelectedNodes(Node[] selection) throws PropertyVetoException { 386 getExplorerManager().setSelectedNodes(selection); 387 } 388 } 389 | Popular Tags |