Changeset 8045


Ignore:
Timestamp:
2004-08-24T16:35:53+12:00 (20 years ago)
Author:
mdewsnip
Message:

Removed all the undo crap out of here (which wasn't complete and wasn't enabled).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/gli/src/org/greenstone/gatherer/file/RecycleBin.java

    r8041 r8045  
    4747import javax.swing.tree.*;
    4848import org.greenstone.gatherer.Gatherer;
    49 import org.greenstone.gatherer.file.FileJob;
    5049import org.greenstone.gatherer.file.FileNode;
    51 import org.greenstone.gatherer.file.FileQueue;
    5250import org.greenstone.gatherer.file.FileSystemModel;
    53 import org.greenstone.gatherer.msm.MetadataXMLFile;
    54 import org.greenstone.gatherer.msm.Metadata;
    5551import org.greenstone.gatherer.util.DragComponent;
    5652import org.greenstone.gatherer.util.DragGroup;
    5753import org.greenstone.gatherer.util.Utility;
    58 /** Manages the rather complex task of undoing and redoing actions. It does this by storing two queues, undo and redo, containing undo jobs which encapsulate all the information needed to undo or redo an action. It is also important to note that the manage creates a temporary directory, and then places any deleted files in this directory, and saves their associated metadata with them, for the life of the session. This is to facilitate the restoring of deleted files.
    59  * @author John Thompson, Greenstone Digital Library, University of Waikato
    60  * @version 2.3c
    61  */
     54
     55
    6256public class RecycleBin
    6357    extends JButton
    64     implements ActionListener, DragComponent, DropTargetListener {
    65     private ArrayList redo_sources;
    66     private ArrayList undo_sources;
     58    implements DragComponent, DropTargetListener {
     59
    6760    private boolean ignore = false;
    68     private boolean ignore_next = false;
    6961    /** The group encompasses all of the objects you plan to drag and drop within, and ensures that only one has focus (as clearly identified by the colour of the selection field or, in this particular case, the background) and that actions only occur between components in the same group. */
    7062    private DragGroup group;
    7163    /** In order to make this button a drop target we have to create a DropTarget instance with the button as its target. */
    7264    private DropTarget drop_target;
    73     private FileQueue file_queue;
    7465    private FileSystemModel model;
    75     private MetadataXMLFile obsolete_metadata;
    7666    /** What sort of action should a drag resemble. Not really used as we override with custom drag icon. */
    7767    private int drag_action = DnDConstants.ACTION_MOVE;
     
    8070    /** The area covered by the drag ghost, our custom drag icon. */
    8171    private Rectangle ra_ghost = new Rectangle();
    82     private UndoStack redo;
    83     private UndoStack undo;
    84     static final public int FILE_COPY = 1;
    85     static final public int FILE_DELETE = 2;
    86     static final public int FILE_MOVE = 3;
    8772
    88     public RecycleBin() {
     73
     74    public RecycleBin()
     75    {
    8976    super(Utility.getImage("bin.gif"));
    90     this.file_queue = Gatherer.f_man.getQueue();
    9177    this.drop_target = new DropTarget(this, drag_action, this, true);
    9278
     
    9581    setOpaque(true);
    9682
    97     // Creation
    98     File recycle_directory = new File(Utility.RECYCLE);
    99     if(!recycle_directory.exists()) {
    100         recycle_directory.mkdirs();
    101         recycle_directory.deleteOnExit();
    102     }
    103     this.model = new FileSystemModel(new FileNode(recycle_directory, "Undo"));
    104     obsolete_metadata = new MetadataXMLFile(); // This GDM is never saved.
    105     redo = new UndoStack(false);
    106     redo_sources = new ArrayList();
    107     undo = new UndoStack(true);
    108     undo_sources = new ArrayList();
    109     //if(Gatherer.debug != null) {
    110     //   showTree();
    111     //}
     83    this.model = new FileSystemModel(new FileNode(new File(Utility.RECYCLE), "Undo"));
    11284    }
    11385
    114     public void actionPerformed(ActionEvent event) {
    115     // Is this an undo event source...
    116     if(undo_sources.contains(event.getSource())) {
    117         UndoJob undo_job = undo.pop();
    118         undo_job.action(true, file_queue);
    119         // Now retrieve all other undo jobs with the same job-number and action them
    120         while((undo_job = undo.getJob(undo_job.ID())) != null) {
    121         undo_job.action(true, file_queue);
    122         }
    123     }
    124     // Or a redo one.
    125     else if(redo_sources.contains(event.getSource())) {
    126         UndoJob redo_job = redo.pop();
    127         redo_job.action(false, file_queue);
    128         // Now retrieve all other redo jobs with the same job-number and action them
    129         while((redo_job = redo.getJob(redo_job.ID())) != null) {
    130         redo_job.action(false, file_queue);
    131         }
    132     }
    133     }
    134 
    135     public void addMetadata(File file, ArrayList metadatum) {
    136     for(int i = 0; metadatum != null && i < metadatum.size(); i++) {
    137         Metadata metadata = (Metadata) metadatum.get(i);
    138         ///ystem.err.println("UndoMetadata: " + file.getAbsolutePath() + " => " + metadata);
    139         String file_path = file.getAbsolutePath().replace('\\', '/');
    140         obsolete_metadata.addMetadata(file_path, metadata, true);
    141     }
    142     }
    143 
    144     public void addUndo(long id, int type, DragComponent source_model, FileNode source_parent, DragComponent target_model, FileNode record, boolean undo_event) {
    145     if(target_model == null) {
    146         target_model = this;
    147     }
    148     UndoJobAdder job_adder = new UndoJobAdder(id, type, source_model, source_parent, target_model, record, undo_event);
    149     SwingUtilities.invokeLater(job_adder);
    150     }
    151 
    152     public void clear() {
    153     undo.clear();
    154     redo.clear();
    155     }
    15686
    15787    /** 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 repair the 'spoilt' region left by its ghost. */
     
    15989    }
    16090
    161     public void destroy() {
    162     // Remove all references of this as a listener
    163     for(int i = 0; i < redo_sources.size(); i++) {
    164         AbstractButton source = (AbstractButton) redo_sources.get(i);
    165         source.removeActionListener(this);
    166     }
    167     for(int j = 0; j < undo_sources.size(); j++) {
    168         AbstractButton source = (AbstractButton) undo_sources.get(j);
    169         source.removeActionListener(this);
    170     }
    171     redo_sources = null;
    172     undo_sources = null;
    173     redo = null;
    174     undo = null;
    175     obsolete_metadata = null;
    176     file_queue = null;
    177     }
    17891
    17992    /** Any implementation of DropTargetListener must include this method so we can be notified when the drag focus enters this component. We want to provide some sort of indication whether the current component is an acceptable drop target as well as indicating focus. */
    18093    public void dragEnter(DropTargetDragEvent event) {
    181     //ystem.err.println("Drag entered");
    18294    group.grabFocus(this);
    18395    setBackground(Gatherer.config.getColor("coloring.button_selected_background", true));
     
    18799    /** Any implementation of DropTargetListener must include this method so we can be notified when the drag focus leaves this component. We need to indicate that we have lost focus. */
    188100    public void dragExit(DropTargetEvent event) {
    189     //ystem.err.println("Drag exitted");
    190101    setBackground(Gatherer.config.getColor("coloring.button_background", true));
    191102    setForeground(Gatherer.config.getColor("coloring.button_foreground", true));
     
    224135        source_nodes[i] = (FileNode) selection[i].getLastPathComponent();
    225136        }
    226         ///ystem.err.println("Dropped files vector contains " + new_files.size() + " files.");
    227137        event.acceptDrop(drag_action);
    228138        // Action delete
     
    246156
    247157    /** Used to notify this component that it has gained focus by some method other that mouse focus. */
    248     public void gainFocus(){
    249     }
    250 
    251     public ArrayList getMetadata(File file) {
    252     ///ystem.err.println("UndoMetadata: " + file.getAbsolutePath());
    253     return obsolete_metadata.getMetadata(file.getAbsolutePath(), true, new ArrayList(), file, false);
     158    public void gainFocus() {
    254159    }
    255160
    256161    /** Any implementation of DragComponent must include this method so that a outsider can get at the underlying tree model behind the component. */
    257162    public FileSystemModel getTreeModel(){
    258     return (FileSystemModel) model;
     163    return (FileSystemModel) model;
    259164    }
    260165
     
    264169
    265170    /** This method is used to inform this component when it loses focus by means other than a drag mouse event, and should indicate this somehow. */
    266     public void loseFocus(){
    267     }
    268 
    269     public void registerRedoSource(AbstractButton source) {
    270     if(!redo_sources.contains(source)) {
    271         redo_sources.add(source);
    272         source.addActionListener(this);
    273     }
    274     }
    275 
    276     public void registerUndoSource(AbstractButton source) {
    277     if(!undo_sources.contains(source)) {
    278         undo_sources.add(source);
    279         source.addActionListener(this);
    280     }
     171    public void loseFocus() {
    281172    }
    282173
     
    284175    this.group = group;
    285176    }
    286 
    287     public void undoAll() {
    288     FileQueue immediate_queue = new FileQueue(true);
    289     UndoJob undo_job = null;
    290     while((undo_job = undo.pop()) != null) {
    291         undo_job.action(true, immediate_queue);
    292         // Now retrieve all other undo jobs with the same job-number and action them
    293         while((undo_job = undo.getJob(undo_job.ID())) != null) {
    294         undo_job.action(true, immediate_queue);
    295         }
    296     }
    297     immediate_queue.run();
    298     // Returns only when all undo actions complete.
    299     }
    300 
    301     private void showTree() {
    302     JDialog dialog = new JDialog(Gatherer.g_man, "Recycle Bin Model");
    303     dialog.setSize(new Dimension(400,300));
    304     JPanel content_pane = (JPanel) dialog.getContentPane();
    305     JTree tree = new JTree(model);
    306     content_pane.setLayout(new BorderLayout());
    307     content_pane.add(new JScrollPane(tree), BorderLayout.CENTER);
    308     dialog.show();
    309     }
    310 
    311     private class UndoJob {
    312     private FileNode record = null;
    313     private FileNode source_parent = null;
    314     private DragComponent source_model = null;
    315     private DragComponent target_model = null;
    316     private long id = 0;
    317     private int type = -1;
    318     private TreePath record_path = null;
    319     private TreePath source_parent_path = null;
    320     /** Undo file action Constructor.
    321      * @param id A unique <i>long</i> id number for all actions associated with a certain gesture.
    322      * @param source_model The source <strong>DragComponent</strong> where the new record originally came from. If this is <i>null</i> then it is assumed you are interested in using the 'recycle' bin model.
    323      * @param source_parent The previous parent <strong>FileNode</strong> of the new record.
    324      * @param target_model The target <strong>DragComponent</strong> where the new record is now.
    325      * @param record The new <strong>FileNode</strong> itself.
    326      * @param type An <i>int</i> indicating the action that has occured, not what undo action is needed.
    327      */
    328     public UndoJob(long id, DragComponent source_model, FileNode source_parent, DragComponent target_model, FileNode record, int type) {
    329         this.id = id;
    330         this.record = record;
    331         if(record != null) {
    332         this.record_path = new TreePath(record.getPath());
    333         }
    334         this.source_model = source_model;
    335         this.source_parent = source_parent;
    336         if(source_parent != null) {
    337         this.source_parent_path = new TreePath(source_parent.getPath());
    338         }
    339         this.target_model = target_model;
    340         this.type = type;
    341     }
    342 
    343     public void action(boolean is_undo, FileQueue file_queue) {
    344         // Retrieve the lastest version of each file record
    345         FileNode latest_record = null;
    346         FileNode latest_source_parent = null;
    347         if(target_model != null && record_path != null) {
    348         ///ystem.err.println("Retrieving latest version of record from " + target_model + ".");
    349         latest_record = ((FileSystemModel)target_model.getTreeModel()).getNode(record_path);
    350         }
    351         if(source_model != null && source_parent_path != null) {
    352         ///ystem.err.println("Retrieving latest version of source parent.");
    353         latest_source_parent = ((FileSystemModel)source_model.getTreeModel()).getNode(source_parent_path);
    354         }
    355         // Of course if there are no newer versions, stick to the ones we've already got.
    356         if(latest_record == null) {
    357         ///ystem.err.println("Using original record.");
    358         latest_record = record;
    359         }
    360         if(latest_source_parent == null) {
    361         ///ystem.err.println("Using original source parent.");
    362         latest_source_parent = source_parent;
    363         }
    364                 // Heres the fraction, too much friction.
    365         switch(type) {
    366         case FILE_COPY:
    367         // To undo a file copy we issue a delete file action on the destination file record.
    368         file_queue.addJob(id, target_model, latest_record, source_model, latest_source_parent, FileJob.DELETE, !is_undo, true, false);
    369         break;
    370         case FILE_DELETE:
    371         // To undo a file delete we issue a copy file action from our recycle bin.
    372         file_queue.addJob(id, target_model, latest_record, source_model, latest_source_parent, FileJob.MOVE, !is_undo, true, false);
    373         break;
    374         case FILE_MOVE:
    375         // This may be a legitimate move, or may be a side effect of an undelete. If the formed source model and parent will be non-null.
    376         if(source_model != null && source_parent != null) {
    377             // To undo a file move we issue a move file action to return it to where it was.
    378             file_queue.addJob(id, target_model, latest_record, source_model, latest_source_parent, FileJob.MOVE, !is_undo, true, false);
    379         }
    380         // Otherwise we perform another delete.
    381         else {
    382             file_queue.addJob(id, target_model, latest_record, source_model, latest_source_parent, FileJob.DELETE, !is_undo, true, false);
    383         }
    384         break;
    385         default:
    386         ///ystem.err.println("Unknown code.");
    387         }
    388     }
    389 
    390     public FileNode getRecord() {
    391         return record;
    392     }
    393 
    394     public long ID() {
    395         return id;
    396     }
    397     }
    398 
    399     private class UndoJobAdder
    400     implements Runnable {
    401     private boolean undo_event;
    402     private FileNode record;
    403     private FileNode source_parent;
    404     private DragComponent source_model;
    405     private DragComponent target_model;
    406     private int type;
    407     private long id;
    408     public UndoJobAdder(long id, int type, DragComponent source_model, FileNode source_parent, DragComponent target_model, FileNode record, boolean undo_event) {
    409         this.id = id;
    410         this.record = record;
    411         this.source_model = source_model;
    412         this.source_parent = source_parent;
    413         this.target_model = target_model;
    414         this.type = type;
    415         this.undo_event = undo_event;
    416     }
    417     public void run() {
    418         UndoJob job = new UndoJob(id, source_model, source_parent, target_model, record, type);
    419         if(undo_event) {
    420         undo.push(job);
    421         }
    422         else {
    423         redo.push(job);
    424         }
    425     }
    426     }
    427 
    428     private class UndoStack
    429     extends LinkedList {
    430     private boolean enabled = false;
    431     private boolean undo;
    432     private int pos = 0;
    433     public UndoStack(boolean undo) {
    434         this.undo = undo;
    435     }
    436     public void clear() {
    437         super.clear();
    438         pos = 0;
    439         if(enabled) {
    440         setEnabled(false);
    441         }
    442     }
    443     public UndoJob getJob(long id) {
    444         UndoJob job = null;
    445         while(job == null && pos < size()) {
    446         UndoJob temp = (UndoJob) get(pos);
    447         if(temp.ID() == id) {
    448             job = temp;
    449             remove(temp);
    450         }
    451         else {
    452             pos++;
    453         }
    454         }
    455         if(size() == 0) {
    456         setEnabled(false);
    457         pos = 0;
    458         }
    459         return job;
    460     }
    461     public void push(UndoJob job) {
    462         addFirst(job);
    463         pos = 0;
    464         if(!enabled) {
    465         setEnabled(true);
    466         }
    467     }
    468     public UndoJob pop() {
    469         UndoJob job = null;
    470         if(size() > 0) {
    471         job = (UndoJob) removeFirst();
    472         if(size() == 0 && enabled) {
    473             setEnabled(false);
    474             pos = 0;
    475         }
    476         }
    477         return job;
    478     }
    479     public void reset() {
    480         pos = 0;
    481     }
    482     private void setEnabled(boolean state) {
    483         ArrayList sources;
    484         if(undo) {
    485         sources = undo_sources;
    486         }
    487         else {
    488         sources = redo_sources;
    489         }
    490         for(int i = 0; i < sources.size(); i++) {
    491         AbstractButton source = (AbstractButton) sources.get(i);
    492         source.setEnabled(state);
    493         }
    494         enabled = state;
    495     }
    496     }
    497177}
Note: See TracChangeset for help on using the changeset viewer.