Changeset 4366 for trunk/gli/src/org/greenstone/gatherer/gui/tree
- Timestamp:
- 2003-05-27T15:57:37+12:00 (21 years ago)
- Location:
- trunk/gli/src/org/greenstone/gatherer/gui/tree
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/gli/src/org/greenstone/gatherer/gui/tree/DragTree.java
r4313 r4366 21 21 22 22 public class DragTree 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 23 extends JTree 24 implements Autoscroll, DragGestureListener, DragSourceListener, DropTargetListener, DragComponent, TreeSelectionListener { 25 /** The normal background color. */ 26 private Color background_color; 27 /** The normal foreground color. */ 28 private Color foreground_color; 29 /** The Group this component belongs to. */ 30 private DragGroup group; 31 /** The image to use for the disabled background. */ 32 private ImageIcon disabled_background; 33 /** The image to use for a normal background. */ 34 private ImageIcon normal_background; 35 /** The icon to use for multiple node drag'n'drops. We decided against using the windows paradigm or a block of x horizontal lines for x files. */ 36 private ImageIcon multiple_icon = new ImageIcon("resource"+File.separator+"multiple.gif"); 37 /** The default drag action, although its not that important as we provide custom icons during drags. */ 38 private int drag_action = DnDConstants.ACTION_MOVE; 39 /** The location of the last ghost drawn, so that we can repair the 'spoilt' area. */ 40 private Point pt_last = null; 41 /** The region borderer by the lower cue line. */ 42 private Rectangle lower_cue_line; 43 /** The region covered by the drag ghost icon. */ 44 private Rectangle ra_ghost = new Rectangle(); 45 /** The region borderer by the upper cue line. */ 46 private Rectangle upper_cue_line; 47 /** The identifying name of this Tree. */ 48 private String name; 49 /** The last tree path the drag was hovered over. */ 50 private TreePath previous_path = null; 51 static private final Color TRANSPARENT_COLOR = new Color(0,0,0,0); 52 /** The distance from the edge of the current view within the scroll bar which if entered causes the view to scroll. */ 53 static private final int AUTOSCROLL_MARGIN = 12; 54 55 public DragTree(String name, String background_name) { 56 super(); 57 init(name, background_name); 58 } 59 60 public DragTree(String name, TreeModel model, String background_name) { 61 super(model); 62 init(name, background_name); 63 // Connection 64 setModel(model); 65 } 66 67 public void init(String name, String background_name) { 68 // Init 69 this.name = name; 70 if(background_name != null) { 71 this.disabled_background = new ImageIcon("background.gif"); 72 this.normal_background = new ImageIcon(background_name); 73 } 74 75 // Creation 76 this.putClientProperty("JTree.lineStyle", "Angled"); 77 this.setAutoscrolls(true); 78 this.setEditable(false); 79 this.setLargeModel(true); 80 this.setOpaque(true); 81 this.setSelectionModel(new DragTreeSelectionModel(this)); 82 // Connection 83 addTreeSelectionListener(this); 84 85 DragTreeCellRenderer renderer = new DragTreeCellRenderer(); 86 //make the renderer paint nodes as transparent when not selected 87 //renderer.setBackgroundNonSelectionColor(new Color(0,0,0,0)); 88 setCellRenderer(renderer); 89 89 90 90 // Drag'n'drop Setup 91 91 // Drag source setup. 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 92 DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(this, drag_action, this); 93 // Drop destination setup. 94 new DropTarget(this, drag_action, this, true); 95 } 96 97 // Autoscroll Interface - Scroll because the mouse cursor is in our scroll zone.<br> 98 // The following code was borrowed from the book:<br> 99 // Java Swing<br> 100 // By Robert Eckstein, Marc Loy & Dave Wood<br> 101 // Paperback - 1221 pages 1 Ed edition (September 1998)<br> 102 // O'Reilly & Associates; ISBN: 156592455X<br> 103 // The relevant chapter of which can be found at:<br> 104 // http://www.oreilly.com/catalog/jswing/chapter/dnd.beta.pdf<br> 105 // But I've probably tortured it beyond all recognition anyway. 106 public void autoscroll(Point pt) { 107 // Figure out which row we're on. 108 int row = getRowForLocation(pt.x, pt.y); 109 // If we are not on a row then ignore this autoscroll request 110 if (row < 0) return; 111 Rectangle bounds = getBounds();// Yes, scroll up one row 112 // Now decide if the row is at the top of the screen or at the bottom. We do this to make the previous row (or the next row) visible as appropriate. If we're at the absolute top or bottom, just return the first or last row respectively. 113 // Is row at top of screen? 114 if(pt.y + bounds.y <= AUTOSCROLL_MARGIN) { 115 115 // Yes, scroll up one row 116 117 118 119 120 121 122 123 116 if(row <= 0) { 117 row = 0; 118 } 119 else { 120 row = row - 1; 121 } 122 } 123 else { 124 124 // No, scroll down one row 125 126 127 128 129 130 131 132 133 */ 134 135 136 137 138 139 125 if(row < getRowCount() - 1) { 126 row = row + 1; 127 } 128 } 129 this.scrollRowToVisible(row); 130 } 131 132 /** In order for the appearance to be consistant, given we may be in the situation where the pointer has left our focus but the ghost remains, this method allows other members of the GGroup to tell this component to clear its ghost. 133 */ 134 public void clearGhost() { 135 // Erase the last ghost image and cue line 136 paintImmediately(ra_ghost.getBounds()); 137 } 138 139 /** Any implementation of DragSourceListener must include this method so we can be notified when the drag event ends (somewhere else), which will in turn remove actions. 140 140 * @param event A <strong>DragSourceDropEvent</strong> containing all the information about the end of the drag event. 141 141 */ 142 143 142 public void dragDropEnd(DragSourceDropEvent event) { 143 if(event.getDropSuccess()) { 144 144 // Do whatever I do when the drop is successful. 145 146 147 145 } 146 } 147 /** Any implementation of DragSourceListener must include this method so we can be notified when the drag focus enters this component. 148 148 * @param event A <strong>DragSourceDragEvent</strong> containing all the information 149 149 * about the drag event. 150 150 */ 151 152 153 154 151 public void dragEnter(DragSourceDragEvent event) { 152 // Handled elsewhere. 153 } 154 /** Any implementation of DropTargetListener must include this method so we can be notified when the drag focus enters this component, which in this case is to grab focus from within our group. 155 155 * @param event A <strong>DropTargetDragEvent</strong> containing all the information about the drag event. 156 156 */ 157 158 159 160 157 public void dragEnter(DropTargetDragEvent event) { 158 group.grabFocus(this); 159 } 160 /** Any implementation of DragSourceListener must include this method so we can be notified when the drag focus leaves this component. 161 161 * @param event A <strong>DragSourceEvent</strong> containing all the information about the drag event. 162 162 */ 163 164 165 166 167 163 public void dragExit(DragSourceEvent event) { 164 clearGhost(); 165 } 166 167 /** Any implementation of DropTargetListener must include this method 168 168 * so we can be notified when the drag focus leaves this component. 169 169 * @param event A DropTargetEvent containing all the information 170 170 * about the drag event. 171 171 */ 172 173 174 175 176 172 public void dragExit(DropTargetEvent event) { 173 clearGhost(); 174 } 175 176 /** Any implementation of DragGestureListener must include this method 177 177 * so we can be notified when a drag action has been noticed, thus a 178 178 * drag action has begun. … … 180 180 * the drag event. 181 181 */ 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 182 public void dragGestureRecognized(DragGestureEvent event) { 183 // Disable editing, unless you want to have the edit box pop-up part way through dragging. 184 this.setEditable(false); 185 // We need this to find one of the selected nodes. 186 Point origin = event.getDragOrigin(); 187 TreePath path = this.getPathForLocation(origin.x, origin.y); 188 // Taking into account our delayed model of selection, it is possible the user has performed a select and drag in one click. Here we utilize the Windows paradigm like so: If the node at the origin of the drag and drop is already in our selection then we perform multiple drag and drop. Otherwise we recognise that this is a distinct drag-drop and move only the origin node. 189 if(!isPathSelected(path)) { 190 ((DragTreeSelectionModel)selectionModel).setImmediate(true); 191 setSelectionPath(path); 192 } 193 // Now update the selection stored as far as the group is concerned. 194 group.setSelection(getSelectionPaths()); 195 group.setSource(this); 196 // First grab ghost. 197 group.grabFocus(this); 198 // Ghost Image stuff. 199 if(path != null) { 200 Rectangle rect = this.getPathBounds(path); 201 group.mouse_offset = new Point(origin.x - rect.x, origin.y - rect.y); 202 202 // Create the ghost image. 203 203 // Retrieve the selected files. 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 204 int selection_count = getSelectionCount(); 205 if(selection_count > 0) { 206 JLabel label; 207 if(selection_count == 1) { 208 TreePath node_path = getSelectionPath(); 209 FileNode node = (FileNode) path.getLastPathComponent(); 210 label = new JLabel(node.toString(), ((DefaultTreeCellRenderer)getCellRenderer()).getLeafIcon(), JLabel.CENTER); 211 } 212 else { 213 String title = getSelectionCount() + " files"; 214 label = new JLabel(title, ((DefaultTreeCellRenderer)getCellRenderer()).getClosedIcon(), JLabel.CENTER); 215 title = null; 216 } 217 // The layout manager normally does this. 218 Dimension label_size = label.getPreferredSize(); 219 label.setSize(label_size); 220 label.setBackground(TRANSPARENT_COLOR); 221 label.setOpaque(true); 222 // Get a buffered image of the selection for dragging a ghost image. 223 group.image_ghost = new BufferedImage(label_size.width, label_size.height, BufferedImage.TYPE_INT_ARGB_PRE); 224 label_size = null; 225 // Get a graphics context for this image. 226 Graphics2D g2 = group.image_ghost.createGraphics(); 227 // Make the image ghostlike 228 g2.setComposite(AlphaComposite.getInstance (AlphaComposite.SRC, 0.5f)); 229 // Ask the cell renderer to paint itself into the BufferedImage 230 label.paint(g2); 231 g2 = null; 232 label = null; 233 try { 234 event.startDrag(new Cursor(Cursor.DEFAULT_CURSOR), group.image_ghost, new Point(5,5), new StringSelection("dummy"), this); 235 //dragging = true; 236 } 237 catch(Exception error) { 238 error.printStackTrace(); 239 } 240 } 241 } 242 } 243 244 /** Implementation side-effect. 245 245 * @param event A DragSourceDragEvent containing all the information about the drag event. 246 246 */ 247 248 249 250 247 public void dragOver(DragSourceDragEvent event) { 248 } 249 250 /** Any implementation of DropTargetListener must include this method 251 251 * so we can be notified when the drag moves in this component. 252 252 * @param event A DropTargetDragEvent containing all the information 253 253 * about the drag event. 254 254 */ 255 256 257 258 259 260 261 262 263 255 public void dragOver(DropTargetDragEvent event) { 256 // Draw the mouse ghost 257 Graphics2D g2 = (Graphics2D) getGraphics(); 258 Point pt = event.getLocation(); 259 if(pt_last != null && pt.equals(pt_last)) { 260 return; 261 } 262 pt_last = pt; 263 if(!DragSource.isDragImageSupported()) { 264 264 // Erase the last ghost image and cue line 265 265 paintImmediately(ra_ghost.getBounds()); 266 266 // Remember where you are about to draw the new ghost image 267 267 ra_ghost.setRect(pt.x - group.mouse_offset.x, pt.y - group.mouse_offset.y, group.image_ghost.getWidth(), group.image_ghost.getHeight()); 268 268 // Draw the ghost image 269 270 271 272 273 269 g2.drawImage(group.image_ghost, AffineTransform.getTranslateInstance(ra_ghost.getX(), ra_ghost.getY()), null); 270 } 271 // Now we highlight the target node if it is a valid drop target. Of course we don't bother if we are still over a node which has already been identified as to whether its a drop target. 272 TreePath target_path = this.getPathForLocation(pt.x, pt.y); 273 if(previous_path == null || target_path != null && !target_path.equals(previous_path)) { 274 274 // Immediately clear the old cue lines. 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 275 if(upper_cue_line != null && lower_cue_line != null) { 276 paintImmediately(upper_cue_line.getBounds()); 277 paintImmediately(lower_cue_line.getBounds()); 278 } 279 if(isValidDrop(target_path)) { 280 ///ystem.err.println("Valid. Painting cues."); 281 // Get the drop target's bounding rectangle 282 Rectangle raPath = getPathBounds(target_path); 283 // Cue line bounds (2 pixels beneath the drop target) 284 upper_cue_line = new Rectangle(0, raPath.y + (int)raPath.getHeight(), getWidth(), 2); 285 lower_cue_line = new Rectangle(0, raPath.y, getWidth(), 2); 286 g2.setColor(((DefaultTreeCellRenderer)cellRenderer).getBackgroundSelectionColor()); // The cue line color 287 g2.fill(upper_cue_line); // Draw the cue line 288 g2.fill(lower_cue_line); 289 } 290 else { 291 upper_cue_line = null; 292 lower_cue_line = null; 293 } 294 } 295 } 296 297 /** Any implementation of DropTargetListener must include this method 298 298 * so we can be notified when the drag ends, ie the transferable is 299 299 * dropped. … … 301 301 * about the end of the drag event. 302 302 */ 303 304 305 306 307 303 public void drop(DropTargetDropEvent event) { 304 ///start = System.currentTimeMillis(); 305 ///ystem.err.println("Drop target drop: " + this); 306 event.acceptDrop(drag_action); 307 if(!name.equals(Utility.WORKSPACE_TREE)) { 308 308 // Determine what node we dropped over. 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 309 Point pt = event.getLocation(); 310 TreePath target_path = this.getPathForLocation(pt.x, pt.y); 311 FileNode target = null; 312 if(target_path != null) { 313 if(isValidDrop(target_path)) { 314 target = (FileNode) target_path.getLastPathComponent(); 315 } 316 else { 317 // Warn that this is an invalid drop. 318 JOptionPane.showMessageDialog(Gatherer.g_man, Gatherer.dictionary.get("FileActions.InvalidTarget"), Gatherer.dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE); 319 } 320 } 321 else { 322 target = (FileNode) getModel().getRoot(); 323 } 324 target_path = null; 325 pt = null; 326 if(target != null) { 327 ///ystem.err.println("Valid drop."); 328 TreePath[] selection = group.getSelection(); 329 if(target != null) { 330 FileNode[] source_nodes = new FileNode[selection.length]; 331 for(int i = 0; i < source_nodes.length; i++) { 332 source_nodes[i] = (FileNode) selection[i].getLastPathComponent(); 333 } 334 Gatherer.f_man.action(group.getSource(), source_nodes, this, target); 335 source_nodes = null; 336 } 337 group.setSelection(null); 338 group.setSource(null); 339 selection = null; 340 target = null; 341 } 342 } 343 else { 344 344 // Warn that this is an invalid drop. 345 346 347 348 349 350 351 352 345 JOptionPane.showMessageDialog(Gatherer.g_man, Gatherer.dictionary.get("FileActions.ReadOnlyTarget"), Gatherer.dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE); 346 } 347 // Clear up the group.image_ghost 348 paintImmediately(ra_ghost.getBounds()); 349 event.getDropTargetContext().dropComplete(true); 350 } 351 352 /** Any implementation of DragSourceListener must include this method 353 353 * so we can be notified when the action to be taken upon drop changes. 354 354 * @param event A DragSourceDragEvent containing all the information 355 355 * about the drag event. 356 356 */ 357 358 359 360 357 public void dropActionChanged(DragSourceDragEvent event) { 358 } 359 360 /** Any implementation of DropTargetListener must include this method 361 361 * so we can be notified when the action to be taken upon drop changes. 362 362 * @param event A DropTargetDragEvent containing all the information 363 363 * about the drag event. 364 364 */ 365 366 367 368 365 public void dropActionChanged(DropTargetDragEvent event) { 366 } 367 368 /** Used to notify this component that it has gained focus. It should 369 369 * make some effort to inform the user of this. 370 370 */ 371 372 373 374 375 376 377 371 public void gainFocus() { 372 ///ystem.err.println("Gained focus: " + this); 373 ((DragTreeCellRenderer)cellRenderer).gainFocus(); 374 repaint(); 375 } 376 377 /** Autoscroll Interface... 378 378 * The following code was borrowed from the book: 379 379 * Java Swing … … 387 387 * the tree is in. This makes it a bit messy. 388 388 */ 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 389 public Insets getAutoscrollInsets() 390 { 391 Rectangle raOuter = this.getBounds(); 392 Rectangle raInner = this.getParent().getBounds(); 393 return new Insets(raInner.y - raOuter.y + AUTOSCROLL_MARGIN, 394 raInner.x - raOuter.x + AUTOSCROLL_MARGIN, 395 raOuter.height - raInner.height - raInner.y + raOuter.y + AUTOSCROLL_MARGIN, 396 raOuter.width - raInner.width - raInner.x + raOuter.x + AUTOSCROLL_MARGIN); 397 } 398 399 public String getSelectionDetails() { 400 return ((DragTreeSelectionModel)selectionModel).getDetails(); 401 } 402 403 public FileSystemModel getTreeModel() { 404 return (FileSystemModel) getModel(); 405 } 406 407 /** This method is used to inform this component when it loses focus, 408 408 * and should indicate this somehow. 409 409 */ 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 410 public void loseFocus() { 411 ///ystem.err.println("Lost focus: " + this); 412 ((DragTreeCellRenderer)cellRenderer).loseFocus(); 413 repaint(); 414 } 415 416 public void mapDirectory(File file, String title) { 417 try { 418 ((FileSystemModel)treeModel).mapDirectory(file, title); 419 } 420 catch (Exception error) { 421 error.printStackTrace(); 422 } 423 } 424 425 public void paint(Graphics g) { 426 if(disabled_background != null) { 427 int height = getSize().height; 428 int offset = 0; 429 ImageIcon background; 430 if(isEnabled()) { 431 background = normal_background; 432 } 433 else { 434 background = disabled_background; 435 } 436 while((height - offset) > 0) { 437 g.drawImage(background.getImage(), 0, offset, null); 438 offset = offset + background.getIconHeight(); 439 } 440 background = null; 441 } 442 super.paint(g); 443 } 444 445 public void refresh(TreePath path) { 446 ((FileSystemModel)treeModel).refresh(path); 447 } 448 449 public void setBackgroundNonSelectionColor(Color color) { 450 background_color = color; 451 if(isEnabled()) { 452 setBackground(color); 453 ((DefaultTreeCellRenderer)cellRenderer).setBackgroundNonSelectionColor(color); 454 } 455 else { 456 setBackground(Color.lightGray); 457 ((DefaultTreeCellRenderer)cellRenderer).setBackgroundNonSelectionColor(Color.lightGray); 458 } 459 repaint(); 460 } 461 462 public void setBackgroundSelectionColor(Color color) { 463 ((DefaultTreeCellRenderer)cellRenderer).setBackgroundSelectionColor(color); 464 repaint(); 465 } 466 467 /** Override the normal setEnabled so the Tree exhibits a little more 468 468 * change, which in this instance is the background colour changing. 469 469 * @param state Whether this GTree should be in an enabled state. 470 470 */ 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 471 public void setEnabled(boolean state) { 472 super.setEnabled(state); 473 clearSelection(); 474 // Change some colors 475 if(state) { 476 setBackground(background_color); 477 ((DefaultTreeCellRenderer)cellRenderer).setBackgroundNonSelectionColor(background_color); 478 ((DefaultTreeCellRenderer)cellRenderer).setTextNonSelectionColor(foreground_color); 479 } 480 else { 481 setBackground(Color.lightGray); 482 ((DefaultTreeCellRenderer)cellRenderer).setBackgroundNonSelectionColor(Color.lightGray); 483 ((DefaultTreeCellRenderer)cellRenderer).setTextNonSelectionColor(Color.black); 484 } 485 repaint(); 486 } 487 488 public void setGroup(DragGroup group) { 489 this.group = group; 490 } 491 492 /** Determines whether the following selection attempts should go through the normal delayed selection model, or should happen immediately.*/ 493 public void setImmediate(boolean state) { 494 ((DragTreeSelectionModel)selectionModel).setImmediate(state); 495 } 496 497 public void setModel(TreeModel model) { 498 super.setModel(model); 499 if(model instanceof FileSystemModel) { 500 FileSystemModel file_system_model = (FileSystemModel) model; 501 file_system_model.setTree(this); 502 addTreeExpansionListener(file_system_model); 503 addTreeWillExpandListener(file_system_model); 504 file_system_model = null; 505 } 506 } 507 508 /** Ensure that that file node denoted by the given file is selected. */ 509 public void setSelection(File file) { 510 // We know the file exists, and thus that it must exists somewhere in our tree hierarchy. 511 // 1. Retrieve the root node of our tree. 512 FileNode current = (FileNode) getModel().getRoot(); 513 // 2. Find that node in the file parents, keeping track of each intermediate file. 514 ArrayList files = new ArrayList(); 515 while(file != null && !current.toString().equals(file.getName())) { 516 files.add(0, file); 517 file = file.getParentFile(); 518 } 519 if(file == null) { 520 return; 521 } 522 // 3. While there are still remaining intermediate files. 523 while(files.size() > 0) { 524 file = (File) files.remove(0); 525 525 // 3a. Find the next file in the current nodes children. 526 527 528 529 530 531 532 533 534 535 526 boolean found = false; 527 current.map(); 528 for(int i = 0; !found && i < current.getChildCount(); i++) { 529 FileNode child = (FileNode) current.getChildAt(i); 530 if(child.toString().equals(file.getName())) { 531 // 3b. Make the current node this node (if found) and continue. 532 found = true; 533 current = child; 534 } 535 } 536 536 // 3c. If not found then return as this node can't exists somehow. 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 537 if(!found) { 538 return; 539 } 540 } 541 // 4. We should now have the desired node. Remember to make the selection immediate. 542 TreePath path = new TreePath(current.getPath()); 543 setImmediate(true); 544 setSelectionPath(path); 545 setImmediate(false); 546 } 547 548 public void setTextNonSelectionColor(Color color) { 549 foreground_color = color; 550 if(isEnabled()) { 551 ((DefaultTreeCellRenderer)cellRenderer).setTextNonSelectionColor(color); 552 } 553 else { 554 ((DefaultTreeCellRenderer)cellRenderer).setTextNonSelectionColor(Color.black); 555 } 556 repaint(); 557 } 558 559 public void setTextSelectionColor(Color color) { 560 ((DefaultTreeCellRenderer)cellRenderer).setTextSelectionColor(color); 561 repaint(); 562 } 563 564 public String toString() { 565 return name; 566 } 567 568 public void valueChanged(TreeSelectionEvent e) { 569 if(group == null) { 570 570 ///ystem.err.println("Oh my god, this tree has no group: " + this); 571 572 573 574 575 576 577 578 579 580 581 571 } 572 else { 573 group.grabFocus(this); 574 } 575 Gatherer.g_man.menu_bar.setMetaAuditSuffix(getSelectionDetails()); 576 } 577 578 private boolean isValidDrop(TreePath target_path) { 579 boolean valid = false; 580 if(target_path != null) { 581 FileNode target_node = (FileNode) target_path.getLastPathComponent(); 582 582 // We can only continue testing if the node is a folder. 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 583 if(!target_node.isLeaf()) { 584 // Now we check if the node is readonly. 585 if(!target_node.isReadOnly()) { 586 // Finally we check the target path against the paths in the selection to ensure we are not adding to our own ancestors! 587 TreePath[] selection = group.getSelection(); 588 boolean failed = false; 589 for(int i = 0; !failed && selection != null && i < selection.length; i++) { 590 failed = selection[i].isDescendant(target_path); 591 } 592 // Having finally completed all the tests, we can highlight the drop target. 593 if(!failed) { 594 valid = true; 595 } 596 else { 597 ///ystem.err.println("Invalid. Target is descendant of itself."); 598 } 599 } 600 else { 601 ///ystem.err.println("Read only."); 602 } 603 } 604 else { 605 ///ystem.err.println("Leaf node. Children not allowed."); 606 } 607 previous_path = target_path; 608 } 609 else { 610 if(target_path == null) { 611 previous_path = null; 612 } 613 } 614 return valid; 615 } 616 616 } -
trunk/gli/src/org/greenstone/gatherer/gui/tree/DragTreeCellRenderer.java
r4293 r4366 42 42 43 43 public class DragTreeCellRenderer 44 44 extends DefaultTreeCellRenderer { 45 45 46 47 48 46 private boolean in_focus = false; 47 private Color selection_background; 48 private Color selection_foreground; 49 49 50 51 52 53 54 50 public DragTreeCellRenderer() { 51 super(); 52 selection_background = getBackgroundSelectionColor(); 53 selection_foreground = getTextSelectionColor(); 54 } 55 55 56 57 58 59 56 public void gainFocus() { 57 setBackgroundSelectionColor(selection_background); 58 setTextSelectionColor(selection_foreground); 59 } 60 60 61 62 63 64 61 public void loseFocus() { 62 setBackgroundSelectionColor(Color.lightGray); 63 setTextSelectionColor(Color.black); 64 } 65 65 } 66 66
Note:
See TracChangeset
for help on using the changeset viewer.