Changeset 89e7936


Ignore:
Timestamp:
Jun 9, 2010, 2:54:30 PM (10 years ago)
Author:
Michael Seifert <mseifert@…>
Branches:
master
Children:
16b01d3
Parents:
477b694
Message:

WARP serializes all replay objects contained in the opened folder and is capable of retrieving them on click;

Improved program structure to better fit into and MVC pattern

Location:
src/main/java/de/erichseifert/warp
Files:
4 added
8 edited

Legend:

Unmodified
Added
Removed
  • src/main/java/de/erichseifert/warp/ChatMessage.java

    r477b694 r89e7936  
    2222package de.erichseifert.warp;
    2323
     24import java.io.Serializable;
     25
    2426/**
    2527 * Interface that provides the most basic functions a chat message must have.
    2628 * Comparing two <code>ChatMessage</code> objects yields the same result as comparing their time stamps.
    2729 */
    28 public interface ChatMessage extends Comparable<ChatMessage> {
     30public interface ChatMessage extends Comparable<ChatMessage>, Serializable {
    2931        /**
    3032         * Message sent to all players in the game.
  • src/main/java/de/erichseifert/warp/DefaultReplay.java

    r477b694 r89e7936  
    109109                this.version = version;
    110110        }
     111
     112        @Override
     113        public ReplayDescriptor getDescriptor() {
     114                return new ReplayDescriptor(getFile(), getDuration(), getVersion());
     115        }
    111116}
  • src/main/java/de/erichseifert/warp/GameAction.java

    r477b694 r89e7936  
    2222package de.erichseifert.warp;
    2323
     24import java.io.Serializable;
     25
    2426/**
    2527 * Interface that represents a basic action a player has undertaken.
    2628 */
    27 public interface GameAction extends VersionedComponent {
     29public interface GameAction extends VersionedComponent, Serializable {
    2830        /**
    2931         * Returns the point in time when this action has occurred.
  • src/main/java/de/erichseifert/warp/Player.java

    r477b694 r89e7936  
    2323
    2424import java.awt.Color;
     25import java.io.Serializable;
    2526import java.util.List;
    2627
     
    2829 * Interface that provides the most basic functions a player must have.
    2930 */
    30 public interface Player {
     31public interface Player extends Serializable {
    3132
    3233        /**
  • src/main/java/de/erichseifert/warp/Replay.java

    r477b694 r89e7936  
    2323
    2424import java.io.File;
     25import java.io.Serializable;
    2526import java.util.List;
    2627
     
    2829 * Interface that represents a unified interface for any type of replay.
    2930 */
    30 public interface Replay extends VersionedComponent {
     31public interface Replay extends VersionedComponent, Serializable {
    3132        /**
    3233         * Returns the game duration of the replay.
     
    6566         */
    6667        File getFile();
     68
     69        ReplayDescriptor getDescriptor();
    6770}
  • src/main/java/de/erichseifert/warp/WARP.java

    r477b694 r89e7936  
    2222package de.erichseifert.warp;
    2323
     24import java.io.File;
     25import java.util.ArrayList;
     26import java.util.Collection;
     27import java.util.Collections;
     28import java.util.HashSet;
     29import java.util.List;
     30
    2431import javax.swing.UIManager;
    2532import javax.swing.UnsupportedLookAndFeelException;
    2633
    2734import de.erichseifert.warp.gui.ReplayParserGUI;
     35import de.erichseifert.warp.io.SerializingStorage;
     36import de.erichseifert.warp.io.Settings;
     37import de.erichseifert.warp.replays.ReplayParserFactory;
    2838
    2939/**
     
    3141 */
    3242public class WARP {
     43        private static final int walkDepth = 3;
     44
     45        private final List<ReplayDataChangeListener> listeners;
     46        private final SerializingStorage storage;
     47        private final ReplayParserGUI gui;
    3348
    3449        /**
    3550         * Creates a <code>WARP</code> object.
    36          * This constructor does nothing.
    3751         */
    38         private WARP() {
     52        public WARP() {
     53                listeners = new ArrayList<ReplayDataChangeListener>();
     54
     55                storage = new SerializingStorage();
     56
     57                gui = new ReplayParserGUI(this);
     58                gui.setVisible(true);
    3959        }
    4060
     
    5979                }
    6080
    61                 ReplayParserGUI gui = new ReplayParserGUI();
    62                 gui.setVisible(true);
     81                new WARP();
    6382        }
    6483
     84        public void parseDir(File dir) {
     85                if (dir == null) {
     86                        return;
     87                }
     88
     89                // FIXME: Do not delete all files. Check them for being up-to-date
     90                storage.deleteAll();
     91
     92                // Store selected directory for the next startup
     93                Settings.getInstance().setReplayDir(dir.getPath());
     94                // Refresh replay table
     95                Collection<File> replayFiles = walk(dir, walkDepth);
     96                for (File replayFile : replayFiles) {
     97                        Replay replay = ReplayParserFactory.getInstance().getReplayParser(replayFile);
     98                        storage.save(replay);
     99                }
     100
     101                // Notify listeners
     102                fireReplayInfoChanged(storage.getDescriptors());
     103        }
     104
     105        /**
     106         * Retrieves all files in the specified directory, as well as files contained in sub-folders.
     107         * @param dir Directory to be walked.
     108         * @param depth Number of sub-folders to step into.
     109         * @return Collection of files.
     110         */
     111        private Collection<File> walk(File dir, int depth) {
     112                if (!dir.isDirectory()) {
     113                        throw new IllegalArgumentException("The file "+dir.getPath()+" is not a directory.");
     114                }
     115                depth--;
     116                if (depth == -1) {
     117                        return Collections.emptySet();
     118                }
     119                File[] children = dir.listFiles();
     120                Collection<File> files = new HashSet<File>(children.length);
     121                for (File file : children) {
     122                        if (file.isDirectory()) {
     123                                files.addAll(walk(file, depth));
     124                        }
     125                        else {
     126                                files.add(file);
     127                        }
     128                }
     129                return Collections.unmodifiableCollection(files);
     130        }
     131
     132        public Replay getReplay(String path) {
     133                return storage.load(path).get(0);
     134        }
     135
     136        public void addDataChangeListener(ReplayDataChangeListener listener) {
     137                listeners.add(listener);
     138        }
     139
     140        public void removeDataChangeListener(ReplayDataChangeListener listener) {
     141                listeners.remove(listener);
     142        }
     143
     144        protected void fireReplayInfoChanged(Collection<ReplayDescriptor> replayDescriptors) {
     145                for (ReplayDataChangeListener listener : listeners) {
     146                        listener.replaysAvailable(replayDescriptors);
     147                }
     148        }
    65149}
  • src/main/java/de/erichseifert/warp/gui/ReplayParserGUI.java

    r477b694 r89e7936  
    2929import java.awt.event.ActionListener;
    3030import java.io.File;
    31 import java.text.ParseException;
     31import java.sql.Date;
     32import java.text.DateFormat;
    3233import java.util.Collection;
    33 import java.util.Collections;
    34 import java.util.Comparator;
    35 import java.util.HashMap;
    36 import java.util.HashSet;
    37 import java.util.Map;
    3834
    3935import javax.swing.AbstractAction;
     
    6157import javax.swing.table.TableModel;
    6258import javax.swing.table.TableRowSorter;
    63 import javax.swing.text.DateFormatter;
    6459
    6560import de.erichseifert.warp.Replay;
     61import de.erichseifert.warp.ReplayDataChangeListener;
     62import de.erichseifert.warp.ReplayDescriptor;
     63import de.erichseifert.warp.WARP;
    6664import de.erichseifert.warp.gui.ReplayRowFilter.FilterMode;
    6765import de.erichseifert.warp.gui.renderers.sc2replay.SC2ReplayRenderer;
    68 import de.erichseifert.warp.io.Settings;
    69 import de.erichseifert.warp.replays.ReplayParserFactory;
    7066import de.erichseifert.warp.replays.sc2replay.SC2Replay;
    71 import de.erichseifert.warp.util.FileUtil;
    7267
    7368/**
     
    7671 * to display important information. Both components are organized in a <code>JSplitPane</code>.
    7772 */
    78 public class ReplayParserGUI extends JFrame {
    79         private final ReplayParserFactory replayFactory;
     73public class ReplayParserGUI extends JFrame implements ReplayDataChangeListener {
     74        private final WARP warp;
     75
    8076        private final JSplitPane splitPane;
    8177        private final SC2ReplayRenderer replayRenderer;
     
    8682        private final ReplayRowFilter<TableModel> replayTableFilter;
    8783
    88         private final Map<File, Replay> replayCache;
    89 
    90         private File replayDir;
    91 
    9284        /**
    9385         * Creates a new <code>ReplayParserGUI</code> object with the default options.
    9486         */
    95         public ReplayParserGUI() {
     87        public ReplayParserGUI(WARP warp) {
    9688                super("WARP");
    9789
    98                 replayCache = new HashMap<File, Replay>(101);
     90                this.warp = warp;
     91                warp.addDataChangeListener(this);
    9992
    10093                setDefaultCloseOperation(EXIT_ON_CLOSE);
     
    10295                Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    10396                setLocation((screenSize.width - getWidth()) / 2, (screenSize.height - getHeight()) / 2);
    104 
    105                 String replayPath = Settings.getInstance().getReplayDir();
    106                 if (replayPath != null) {
    107                         replayDir = new File(replayPath);
    108                 }
    109 
    110                 replayFactory = ReplayParserFactory.getInstance();
    11197
    11298                // Actions
     
    119105                                int option = fileChooser.showOpenDialog(ReplayParserGUI.this);
    120106                                if (option == JFileChooser.APPROVE_OPTION) {
    121                                         setReplayDir(fileChooser.getSelectedFile());
     107                                        ReplayParserGUI.this.warp.parseDir(fileChooser.getSelectedFile());
    122108                                }
    123109                        }
     
    209195                };
    210196                replayTableSorter = new TableRowSorter<TableModel>(replayTableModel);
    211                 replayTableSorter.setComparator(0, new Comparator<SC2Replay>() {
    212                         @Override
    213                         public int compare(SC2Replay o1, SC2Replay o2) {
    214                                 return o1.getFile().getName().compareTo(o2.getFile().getName());
    215                         }
    216                 });
    217197                replayTableFilter = new ReplayRowFilter<TableModel>(0);
    218198                replayTableSorter.setRowFilter(replayTableFilter);
     
    222202                // Set selection mode
    223203                replayTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    224                 // Create renderer for the replay column
     204                // Create editor for the replay column
    225205                TableColumn replayColumn = replayTable.getColumnModel().getColumn(0);
    226                 replayColumn.setCellRenderer(new DefaultTableCellRenderer() {
    227                         @Override
    228                         public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
    229                                 Component compDefault = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
    230                                 if (compDefault instanceof JLabel) {
    231                                         File archiveFile = ((File) value);
    232                                         String path = FileUtil.getPathRelativeTo(replayDir, archiveFile);
    233                                         ((JLabel) compDefault).setText(path);
    234                                 }
    235                                 return compDefault;
    236                         }
    237                 });
    238                 // Create editor for the replay column
    239206                replayCellEditor = new ReplayCellEditor(replayTable);
    240207                replayColumn.setCellEditor(replayCellEditor);
     
    243210                        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
    244211                                Component comp = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
    245                                 DateFormatter dateFormatter = new DateFormatter();
    246                                 String dateString = "";
    247                                 if (value != null) {
    248                                         try {
    249                                                 dateString = dateFormatter.valueToString(value);
    250                                         } catch (ParseException e) {
    251                                                 // TODO Auto-generated catch block
    252                                                 e.printStackTrace();
    253                                         }
    254                                 }
     212                                Date date = new Date((Long) value);
     213                                DateFormat dateFormat = DateFormat.getDateInstance();
     214                                String dateString = dateFormat.format(date);
    255215                                ((JLabel) comp).setText(dateString);
    256216                                return comp;
     
    264224                                        int selectedIndex = replayTable.getSelectedRow();
    265225                                        if (selectedIndex >= 0) {
     226                                                // FIXME: Renderer should be retrieved by a factory
    266227                                                File replayFile = (File) replayTable.getValueAt(selectedIndex, 0);
    267                                                 Replay replay = replayCache.get(replayFile);
    268                                                 if (replay == null) {
    269                                                         replay = ReplayParserFactory.getInstance().getReplayParser(replayFile);
    270                                                         replayCache.put(replayFile, replay);
    271                                                         // FIXME: Improve caching
    272                                                         if (replayCache.size() > 100) {
    273                                                                 replayCache.clear();
    274                                                         }
    275                                                         // Populate empty row cells
    276                                                         Object[] tableRowFilled = replayToTableRow(replay);
    277                                                         for (int colIndex = 0; colIndex < tableRowFilled.length; colIndex++) {
    278                                                                 replayTable.setValueAt(tableRowFilled[colIndex], selectedIndex, colIndex);
    279                                                         }
    280                                                 }
    281                                                 // FIXME: Renderer should be retrieved by a factory
     228                                                Replay replay = ReplayParserGUI.this.warp.getReplay(replayFile.getAbsolutePath());
    282229                                                splitPane.add(replayRenderer.getRendererComponent((SC2Replay) replay), JSplitPane.LEFT);
    283230                                        }
     
    287234                JScrollPane replayTableScroller = new JScrollPane(replayTable);
    288235                splitPane.add(replayTableScroller, JSplitPane.RIGHT);
    289 
    290                 setReplayDir(replayDir);
    291236        }
    292237
    293         /**
    294          * Sets the directory where the replays are found to the specified directory.
    295          * @param replayDir Directory containing replay files.
    296          */
    297         private void setReplayDir(File replayDir) {
    298                 this.replayDir = replayDir;
    299                 replayTableFilter.setParentDir(replayDir);
    300                 replayCellEditor.setParentDir(replayDir);
    301                 if (replayDir == null) {
    302                         return;
    303                 }
    304                 // Store selected directory for the next startup
    305                 Settings.getInstance().setReplayDir(replayDir.getPath());
    306                 // Refresh replay table
    307                 replayTableModel.setRowCount(0);
    308                 Collection<File> replayFiles = walk(replayDir, 3);
    309                 for (File replayFile : replayFiles) {
    310                         replayTableModel.addRow(new Object[] {replayFile, null, null});
     238        @Override
     239        public void replaysAvailable(Collection<ReplayDescriptor> replayDescriptors) {
     240                for (ReplayDescriptor replayDescriptor : replayDescriptors) {
     241                        replayTableModel.addRow(descriptorToRow(replayDescriptor));
    311242                }
    312243        }
    313244
    314         /**
    315          * Retrieves all files in the specified directory, as well as files contained in sub-folders.
    316          * @param dir Directory to be walked.
    317          * @param depth Number of sub-folders to step into.
    318          * @return Collection of files.
    319          */
    320         private Collection<File> walk(File dir, int depth) {
    321                 if (!dir.isDirectory()) {
    322                         throw new IllegalArgumentException("The file "+dir.getPath()+" is not a directory.");
    323                 }
    324                 depth--;
    325                 if (depth == -1) {
    326                         return Collections.emptySet();
    327                 }
    328                 File[] children = dir.listFiles();
    329                 Collection<File> files = new HashSet<File>(children.length);
    330                 for (File file : children) {
    331                         if (file.isDirectory()) {
    332                                 files.addAll(walk(file, depth));
    333                         }
    334                         else {
    335                                 files.add(file);
    336                         }
    337                 }
    338                 return Collections.unmodifiableCollection(files);
    339         }
    340 
    341         /**
    342          * Creates an array from the specified replay that will be stored in a table.
    343          * @param replay Replay to be disassembled.
    344          * @return Object array.
    345          */
    346         private Object[] replayToTableRow(Replay replay) {
    347                 if (replay != null) {
    348                         return new Object[] {replay.getFile(), replay.getVersion(), replay.getFile().lastModified()};
    349                 }
    350                 return new Object[3];
     245        private static Object[] descriptorToRow(ReplayDescriptor descriptor) {
     246                return new Object[] {
     247                                descriptor.getFile(),
     248                                descriptor.getVersion(),
     249                                descriptor.getFile().lastModified()
     250                };
    351251        }
    352252}
  • src/main/java/de/erichseifert/warp/replays/sc2replay/actions/Order.java

    r477b694 r89e7936  
    2222package de.erichseifert.warp.replays.sc2replay.actions;
    2323
     24import java.io.Serializable;
    2425import java.nio.ByteBuffer;
    2526
     
    5051        public static final OrderCode ID_CLICK = new OrderCode((byte) 0xFF, (short) 0xFF0F);
    5152
    52         public static class OrderCode {
     53        public static class OrderCode implements Serializable {
    5354                private final byte type;
    5455                private final short id;
Note: See TracChangeset for help on using the changeset viewer.