/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* PdeHistory - handler for storing history information about a project Part of the Processing project - http://Proce55ing.net Copyright (c) 2001-03 Ben Fry, Massachusetts Institute of Technology and Casey Reas, Interaction Design Institute Ivrea This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ import java.io.*; import java.util.*; import java.util.zip.*; public class PdeHistory { PdeEditor editor; // why things have been saved for history static final int RUN = 5; static final int SAVE = 6; static final int AUTOSAVE = 7; static final int BEAUTIFY = 8; static final String HISTORY_SEPARATOR = "#################################################"; File historyFile; //OutputStream historyStream; //PrintWriter historyWriter; String historyLast; ActionListener historyMenuListener = new ActionListener() { public void actionPerformed(ActionEvent e) { editor.retrieveHistory(e.getActionCommand()); } }; public PdeHistory(PdeEditor editor) { this.editor = editor; } public void attachMenu(JMenu menu) { if (PdePreferences.getBoolean("history.recording")) { historyMenu = new Menu("History"); menu.add(historyMenu); } } //boolean recordingHistory; JMenu historyMenu; // mode is RUN, SAVE or AUTO public void makeHistory(String program, int mode) { if (!base.recordingHistory) return; //if (historyLast.equals(program) && !externalEditor) return; if ((historyLast != null) && (historyLast.equals(program))) return; String modeStr = null; switch (mode) { case RUN: modeStr = "run"; break; case SAVE: modeStr = "save"; break; case AUTOSAVE: modeStr = "autosave"; break; case BEAUTIFY: modeStr = "beautify"; break; } try { boolean noPreviousHistory = false; ByteArrayOutputStream old = null; if (historyFile.exists()) { InputStream oldStream = new GZIPInputStream(new BufferedInputStream(new FileInputStream(historyFile))); old = new ByteArrayOutputStream(); int c = oldStream.read(); while (c != -1) { old.write(c); c = oldStream.read(); } //return out.toByteArray(); oldStream.close(); } else { noPreviousHistory = true; // rebuild menu } OutputStream historyStream = new GZIPOutputStream(new FileOutputStream(historyFile)); if (old != null) { historyStream.write(old.toByteArray()); } PrintWriter historyWriter = new PrintWriter(new OutputStreamWriter(historyStream)); historyWriter.println(); historyWriter.println(HISTORY_SEPARATOR); Calendar now = Calendar.getInstance(); // 2002 06 18 11 43 29 // when listing, study for descrepancies.. if all are // 2002, then don't list the year and soforth. // for the other end, if all minutes are unique, // then don't show seconds int year = now.get(Calendar.YEAR); int month = now.get(Calendar.MONTH) + 1; int day = now.get(Calendar.DAY_OF_MONTH); int hour = now.get(Calendar.HOUR_OF_DAY); int minute = now.get(Calendar.MINUTE); int second = now.get(Calendar.SECOND); String parseDate = year + " " + month + " " + day + " " + hour + " " + minute + " " + second; String readableDate = now.getTime().toString(); // increment this so sketchbook won't be mangled // each time this format has to change String historyVersion = "1"; //Date date = new Date(); //String datestamp = date.toString(); historyWriter.println(historyVersion + " " + modeStr + " - " + parseDate + " - " + readableDate); historyWriter.println(); historyWriter.println(program); historyWriter.flush(); // ?? historyLast = program; //JMenuItem menuItem = new JMenuItem(modeStr + " - " + readableDate); MenuItem menuItem = new MenuItem(modeStr + " - " + readableDate); menuItem.addActionListener(base.historyMenuListener); base.historyMenu.insert(menuItem, 2); historyWriter.flush(); historyWriter.close(); if (noPreviousHistory) { // to get add the actual menu, to get the 'clear' item in there base.rebuildHistoryMenu(historyFile.getPath()); } } catch (IOException e) { e.printStackTrace(); } } public void retrieveHistory(String selection) { //System.out.println("sel '" + selection + "'"); String readableDate = selection.substring(selection.indexOf("-") + 2); // make history for the current guy makeHistory(textarea.getText(), AUTOSAVE); // mark editor text as having been edited try { BufferedReader reader = new BufferedReader(new InputStreamReader(new GZIPInputStream(new FileInputStream(historyFile)))); String line = null; int historyCount = 0; String historyList[] = new String[100]; try { boolean found = false; while ((line = reader.readLine()) != null) { //System.out.println("->" + line); if (line.equals(PdeEditor.HISTORY_SEPARATOR)) { line = reader.readLine(); if (line.indexOf(readableDate) != -1) { // this is the one found = true; break; } } } if (found) { // read lines until the next separator line = reader.readLine(); // ignored //String sep = System.getProperty("line.separator"); StringBuffer buffer = new StringBuffer(); while ((line = reader.readLine()) != null) { if (line.equals(PdeEditor.HISTORY_SEPARATOR)) break; //textarea.append(line + sep); //buffer.append(line + sep); // JTextPane wants only \n going in buffer.append(line + "\n"); //System.out.println("'" + line + "'"); } //textarea.editorSetText(buffer.toString()); changeText(buffer.toString(), true); historyLast = textarea.getText(); setSketchModified(false); } else { System.err.println("couldn't find history entry for " + "'" + readableDate + "'"); } } catch (IOException e) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } } /* class HistoryMenuListener implements ActionListener { public void actionPerformed(ActionEvent e) { editor.selectHistory(e.getActionCommand); } } */ public void rebuildHistoryMenu(String path) { rebuildHistoryMenu(historyMenu, path); } public void rebuildHistoryMenu(Menu menu, String path) { if (!recordingHistory) return; menu.removeAll(); File hfile = new File(path); if (!hfile.exists()) return; // no history yet MenuItem item = new MenuItem("Clear History"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (!editor.historyFile.delete()) { System.err.println("couldn't erase history"); } rebuildHistoryMenu(historyMenu, editor.historyFile.getPath()); } }); menu.add(item); menu.addSeparator(); try { BufferedReader reader = new BufferedReader(new InputStreamReader(new GZIPInputStream(new FileInputStream(path)))); String line = null; int historyCount = 0; String historyList[] = new String[100]; try { while ((line = reader.readLine()) != null) { //while (line = reader.readLine()) { //while (true) { line = reader.readLine(); //if (line == null) continue; //System.out.println("line: " + line); if (line.equals(PdeEditor.HISTORY_SEPARATOR)) { // next line is the good stuff line = reader.readLine(); int version = Integer.parseInt(line.substring(0, line.indexOf(' '))); if (version == 1) { String whysub = line.substring(2); // after "1 " String why = whysub.substring(0, whysub.indexOf(" -")); //System.out.println("'" + why + "'"); String readable = line.substring(line.lastIndexOf("-") + 2); if (historyList.length == historyCount) { String temp[] = new String[historyCount*2]; System.arraycopy(historyList, 0, temp, 0, historyCount); historyList = temp; } historyList[historyCount++] = why + " - " + readable; } // otherwise don't know what to do } } //System.out.println(line); } catch (IOException e) { e.printStackTrace(); } // add the items to the menu in reverse order /* ActionListener historyMenuListener = new ActionListener() { public void actionPerformed(ActionEvent e) { editor.retrieveHistory(e.getActionCommand()); } }; */ for (int i = historyCount-1; i >= 0; --i) { MenuItem mi = new MenuItem(historyList[i]); mi.addActionListener(historyMenuListener); menu.add(mi); } reader.close(); } catch (IOException e) { e.printStackTrace(); } } }