Ignore:
Timestamp:
2003-05-27T15:57:37+12:00 (21 years ago)
Author:
kjdon
Message:

re-tabbed the code for java

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  
    2121
    2222public class DragTree
    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);
     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);
    8989
    9090          // Drag'n'drop Setup
    9191          // Drag source setup.
    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) {
     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) {
    115115                // Yes, scroll up one row
    116                 if(row <= 0) {
    117                      row = 0;
    118                 }
    119                 else {
    120                      row = row - 1;
    121                 }
    122           }
    123           else {
     116        if(row <= 0) {
     117        row = 0;
     118        }
     119        else {
     120        row = row - 1;
     121        }
     122    }
     123    else {
    124124                // No, scroll down one row
    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.
     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.
    140140      * @param event A <strong>DragSourceDropEvent</strong> containing all the information about the end of the drag event.
    141141      */
    142     public void dragDropEnd(DragSourceDropEvent event) {
    143           if(event.getDropSuccess()) {
     142    public void dragDropEnd(DragSourceDropEvent event) {
     143    if(event.getDropSuccess()) {
    144144                // Do whatever I do when the drop is successful.
    145           }
    146     }
    147      /** Any implementation of DragSourceListener must include this method so we can be notified when the drag focus enters this component.
     145    }
     146    }
     147   /** Any implementation of DragSourceListener must include this method so we can be notified when the drag focus enters this component.
    148148      * @param event A <strong>DragSourceDragEvent</strong> containing all the information
    149149      * about the drag event.
    150150      */
    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.
     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.
    155155      * @param event A <strong>DropTargetDragEvent</strong> containing all the information about the drag event.
    156156      */
    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.
     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.
    161161      * @param event A <strong>DragSourceEvent</strong> containing all the information about the drag event.
    162162      */
    163     public void dragExit(DragSourceEvent event) {
    164           clearGhost();
    165     }
    166 
    167     /** Any implementation of DropTargetListener must include this method
     163    public void dragExit(DragSourceEvent event) {
     164    clearGhost();
     165    }
     166
     167    /** Any implementation of DropTargetListener must include this method
    168168      * so we can be notified when the drag focus leaves this component.
    169169      * @param event A DropTargetEvent containing all the information
    170170      * about the drag event.
    171171      */
    172     public void dragExit(DropTargetEvent event) {
    173           clearGhost();
    174     }
    175 
    176     /** Any implementation of DragGestureListener must include this method
     172    public void dragExit(DropTargetEvent event) {
     173    clearGhost();
     174    }
     175
     176    /** Any implementation of DragGestureListener must include this method
    177177      * so we can be notified when a drag action has been noticed, thus a
    178178      * drag action has begun.
     
    180180      * the drag event.
    181181      */
    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);
     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);
    202202                // Create the ghost image.
    203203                // Retrieve the selected files.
    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.
     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.
    245245      * @param event A DragSourceDragEvent containing all the information about the drag event.
    246246      */
    247     public void dragOver(DragSourceDragEvent event) {
    248     }
    249 
    250     /** Any implementation of DropTargetListener must include this method
     247    public void dragOver(DragSourceDragEvent event) {
     248    }
     249
     250    /** Any implementation of DropTargetListener must include this method
    251251      * so we can be notified when the drag moves in this component.
    252252      * @param event A DropTargetDragEvent containing all the information
    253253      * about the drag event.
    254254      */
    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()) {
     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()) {
    264264                // Erase the last ghost image and cue line
    265                 paintImmediately(ra_ghost.getBounds());
     265        paintImmediately(ra_ghost.getBounds());
    266266                // Remember where you are about to draw the new ghost image
    267                 ra_ghost.setRect(pt.x - group.mouse_offset.x, pt.y - group.mouse_offset.y, group.image_ghost.getWidth(), group.image_ghost.getHeight());
     267        ra_ghost.setRect(pt.x - group.mouse_offset.x, pt.y - group.mouse_offset.y, group.image_ghost.getWidth(), group.image_ghost.getHeight());
    268268                // Draw the ghost image
    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)) {
     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)) {
    274274                // Immediately clear the old cue lines.
    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
     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
    298298      * so we can be notified when the drag ends, ie the transferable is
    299299      * dropped.
     
    301301      * about the end of the drag event.
    302302      */
    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)) {
     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)) {
    308308                // Determine what node we dropped over.
    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 {
     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 {
    344344                // Warn that this is an invalid drop.
    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
     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
    353353      * so we can be notified when the action to be taken upon drop changes.
    354354      * @param event A DragSourceDragEvent containing all the information
    355355      * about the drag event.
    356356      */
    357     public void dropActionChanged(DragSourceDragEvent event) {
    358     }
    359 
    360     /** Any implementation of DropTargetListener must include this method
     357    public void dropActionChanged(DragSourceDragEvent event) {
     358    }
     359
     360    /** Any implementation of DropTargetListener must include this method
    361361      * so we can be notified when the action to be taken upon drop changes.
    362362      * @param event A DropTargetDragEvent containing all the information
    363363      * about the drag event.
    364364      */
    365     public void dropActionChanged(DropTargetDragEvent event) {
    366     }
    367 
    368     /** Used to notify this component that it has gained focus. It should
     365    public void dropActionChanged(DropTargetDragEvent event) {
     366    }
     367
     368    /** Used to notify this component that it has gained focus. It should
    369369      * make some effort to inform the user of this.
    370370      */
    371     public void gainFocus() {
    372           ///ystem.err.println("Gained focus: " + this);
    373           ((DragTreeCellRenderer)cellRenderer).gainFocus();
    374           repaint();
    375     }
    376 
    377     /** Autoscroll Interface...
     371    public void gainFocus() {
     372    ///ystem.err.println("Gained focus: " + this);
     373    ((DragTreeCellRenderer)cellRenderer).gainFocus();
     374    repaint();
     375    }
     376
     377    /** Autoscroll Interface...
    378378      * The following code was borrowed from the book:
    379379      *              Java Swing
     
    387387      * the tree is in. This makes it a bit messy.
    388388      */
    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,
     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,
    408408      * and should indicate this somehow.
    409409      */
    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
     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
    468468      * change, which in this instance is the background colour changing.
    469469      * @param state Whether this GTree should be in an enabled state.
    470470      */
    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);
     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);
    525525                // 3a. Find the next file in the current nodes children.
    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                 }
     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        }
    536536                // 3c. If not found then return as this node can't exists somehow.
    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) {
     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) {
    570570                ///ystem.err.println("Oh my god, this tree has no group: " + this);
    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();
     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();
    582582                // We can only continue testing if the node is a folder.
    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     }
     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    }
    616616}
  • trunk/gli/src/org/greenstone/gatherer/gui/tree/DragTreeCellRenderer.java

    r4293 r4366  
    4242
    4343public class DragTreeCellRenderer
    44     extends DefaultTreeCellRenderer {
     44    extends DefaultTreeCellRenderer {
    4545     
    46     private boolean in_focus = false;
    47     private Color selection_background;
    48     private Color selection_foreground;
     46    private boolean in_focus = false;
     47    private Color selection_background;
     48    private Color selection_foreground;
    4949     
    50     public DragTreeCellRenderer() {
    51           super();
    52           selection_background = getBackgroundSelectionColor();
    53           selection_foreground = getTextSelectionColor();
    54     }
     50    public DragTreeCellRenderer() {
     51    super();
     52    selection_background = getBackgroundSelectionColor();
     53    selection_foreground = getTextSelectionColor();
     54    }
    5555
    56     public void gainFocus() {
    57           setBackgroundSelectionColor(selection_background);
    58           setTextSelectionColor(selection_foreground);
    59     }
     56    public void gainFocus() {
     57    setBackgroundSelectionColor(selection_background);
     58    setTextSelectionColor(selection_foreground);
     59    }
    6060
    61     public void loseFocus() {
    62           setBackgroundSelectionColor(Color.lightGray);
    63           setTextSelectionColor(Color.black);
    64     }
     61    public void loseFocus() {
     62    setBackgroundSelectionColor(Color.lightGray);
     63    setTextSelectionColor(Color.black);
     64    }
    6565}
    6666
Note: See TracChangeset for help on using the changeset viewer.