001: /*
002: * PerspectiveManager.java - Saves view configuration
003: * :tabSize=8:indentSize=8:noTabs=false:
004: * :folding=explicit:collapseFolds=1:
005: *
006: * Copyright (C) 2003 Slava Pestov
007: *
008: * This program is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU General Public License
010: * as published by the Free Software Foundation; either version 2
011: * of the License, or any later version.
012: *
013: * This program is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016: * GNU General Public License for more details.
017: *
018: * You should have received a copy of the GNU General Public License
019: * along with this program; if not, write to the Free Software
020: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
021: */
022:
023: package org.gjt.sp.jedit;
024:
025: import java.io.IOException;
026:
027: import org.xml.sax.Attributes;
028: import org.xml.sax.InputSource;
029: import org.xml.sax.helpers.DefaultHandler;
030:
031: import org.gjt.sp.util.Log;
032: import org.gjt.sp.util.XMLUtilities;
033: import org.gjt.sp.util.IOUtilities;
034:
035: /**
036: * Manages persistence of open buffers and views across jEdit sessions.
037: * @since jEdit 4.2pre1
038: * @author Slava Pestov
039: * @version $Id: PerspectiveManager.java 10964 2007-10-29 20:47:22Z k_satoda $
040: */
041: public class PerspectiveManager {
042: //{{{ isPerspectiveDirty() method
043: /**
044: * We only autosave the perspective if it has changed, to avoid spinning
045: * up the disk on laptops.
046: * @since jEdit 4.2pre13
047: */
048: public static boolean isPerspectiveDirty() {
049: return dirty;
050: } //}}}
051:
052: //{{{ setPerspectiveDirty() method
053: /**
054: * We only autosave the perspective if it has changed, to avoid spinning
055: * up the disk on laptops.
056: * @since jEdit 4.2pre13
057: */
058: public static void setPerspectiveDirty(boolean dirty) {
059: PerspectiveManager.dirty = dirty;
060: } //}}}
061:
062: //{{{ isPerspectiveEnabled() method
063: /**
064: * We disable saving of the perspective while the 'close all' dialog is
065: * showing.
066: * @since jEdit 4.3pre2
067: */
068: public static boolean isPerspectiveEnabled() {
069: return enabled;
070: } //}}}
071:
072: //{{{ setPerspectiveEnabled() method
073: /**
074: * We disable saving of the perspective while the 'close all' dialog is
075: * showing.
076: * @since jEdit 4.3pre2
077: */
078: public static void setPerspectiveEnabled(boolean enabled) {
079: PerspectiveManager.enabled = enabled;
080: } //}}}
081:
082: //{{{ loadPerspective() method
083: public static View loadPerspective(boolean restoreFiles) {
084: if (perspectiveXML == null)
085: return null;
086:
087: if (!perspectiveXML.fileExists())
088: return null;
089:
090: Log.log(Log.MESSAGE, PerspectiveManager.class, "Loading "
091: + perspectiveXML);
092:
093: PerspectiveHandler handler = new PerspectiveHandler(
094: restoreFiles);
095: try {
096: perspectiveXML.load(handler);
097: } catch (IOException e) {
098: Log.log(Log.ERROR, PerspectiveManager.class, e);
099: }
100: return handler.view;
101: } //}}}
102:
103: //{{{ savePerspective() method
104: public static void savePerspective(boolean autosave) {
105: if (!isPerspectiveEnabled())
106: return;
107:
108: if (perspectiveXML == null)
109: return;
110:
111: // backgrounded
112: if (jEdit.getBufferCount() == 0)
113: return;
114:
115: if (!autosave)
116: Log.log(Log.MESSAGE, PerspectiveManager.class, "Saving "
117: + perspectiveXML);
118:
119: String lineSep = System.getProperty("line.separator");
120:
121: SettingsXML.Saver out = null;
122:
123: try {
124: out = perspectiveXML.openSaver();
125: out.writeXMLDeclaration();
126:
127: out
128: .write("<!DOCTYPE PERSPECTIVE SYSTEM \"perspective.dtd\">");
129: out.write(lineSep);
130: out.write("<PERSPECTIVE>");
131: out.write(lineSep);
132:
133: Buffer[] buffers = jEdit.getBuffers();
134: for (int i = 0; i < buffers.length; i++) {
135: Buffer buffer = buffers[i];
136: if (buffer.isNewFile())
137: continue;
138: out.write("<BUFFER AUTORELOAD=\"");
139: out.write(buffer.getAutoReload() ? "TRUE" : "FALSE");
140: out.write("\" AUTORELOAD_DIALOG=\"");
141: out.write(buffer.getAutoReloadDialog() ? "TRUE"
142: : "FALSE");
143: out.write("\">");
144: out.write(XMLUtilities.charsToEntities(
145: buffer.getPath(), false));
146: out.write("</BUFFER>");
147: out.write(lineSep);
148: }
149:
150: View[] views = jEdit.getViews();
151: for (int i = 0; i < views.length; i++) {
152: View view = views[i];
153: // ensures that active view is saved last,
154: // ie created last on next load, ie in front
155: // on next load
156: if (view == jEdit.getActiveView()
157: && i != views.length - 1) {
158: View last = views[views.length - 1];
159: views[i] = last;
160: views[views.length - 1] = view;
161: view = last;
162: }
163:
164: View.ViewConfig config = views[i].getViewConfig();
165: out.write("<VIEW PLAIN=\"");
166: out.write(config.plainView ? "TRUE" : "FALSE");
167: out.write("\">");
168:
169: out.write("<PANES>");
170: out.write(lineSep);
171: out.write(XMLUtilities.charsToEntities(
172: config.splitConfig, false));
173: out.write(lineSep);
174: out.write("</PANES>");
175: out.write(lineSep);
176:
177: out.write("<GEOMETRY X=\"");
178: out.write(String.valueOf(config.x));
179: out.write("\" Y=\"");
180: out.write(String.valueOf(config.y));
181: out.write("\" WIDTH=\"");
182: out.write(String.valueOf(config.width));
183: out.write("\" HEIGHT=\"");
184: out.write(String.valueOf(config.height));
185: out.write("\" EXT_STATE=\"");
186: out.write(String.valueOf(config.extState));
187: out.write("\" />");
188: out.write(lineSep);
189:
190: out.write("<DOCKING LEFT=\"");
191: out.write(config.left == null ? "" : config.left);
192: out.write("\" TOP=\"");
193: out.write(config.top == null ? "" : config.top);
194: out.write("\" RIGHT=\"");
195: out.write(config.right == null ? "" : config.right);
196: out.write("\" BOTTOM=\"");
197: out.write(config.bottom == null ? "" : config.bottom);
198: out.write("\" LEFT_POS=\"");
199: out.write(String.valueOf(config.leftPos));
200: out.write("\" TOP_POS=\"");
201: out.write(String.valueOf(config.topPos));
202: out.write("\" RIGHT_POS=\"");
203: out.write(String.valueOf(config.rightPos));
204: out.write("\" BOTTOM_POS=\"");
205: out.write(String.valueOf(config.bottomPos));
206: out.write("\" />");
207: out.write(lineSep);
208:
209: out.write("</VIEW>");
210: out.write(lineSep);
211: }
212:
213: out.write("</PERSPECTIVE>");
214: out.write(lineSep);
215:
216: out.finish();
217: } catch (IOException io) {
218: Log.log(Log.ERROR, PerspectiveManager.class,
219: "Error saving " + perspectiveXML);
220: Log.log(Log.ERROR, PerspectiveManager.class, io);
221: } finally {
222: IOUtilities.closeQuietly(out);
223: }
224: } //}}}
225:
226: //{{{ Private members
227: private static boolean dirty, enabled = true;
228: private static SettingsXML perspectiveXML;
229:
230: //{{{ Class initializer
231: static {
232: String settingsDirectory = jEdit.getSettingsDirectory();
233: if (settingsDirectory != null) {
234: perspectiveXML = new SettingsXML(settingsDirectory,
235: "perspective");
236: }
237: } //}}}
238:
239: //{{{ PerspectiveHandler class
240: private static class PerspectiveHandler extends DefaultHandler {
241: View view;
242: Buffer currentBuffer;
243: StringBuffer charData;
244: View.ViewConfig config;
245: boolean restoreFiles;
246: String autoReload, autoReloadDialog;
247:
248: PerspectiveHandler(boolean restoreFiles) {
249: this .restoreFiles = restoreFiles;
250: config = new View.ViewConfig();
251: charData = new StringBuffer();
252: }
253:
254: public InputSource resolveEntity(String publicId,
255: String systemId) {
256: return XMLUtilities.findEntity(systemId, "perspective.dtd",
257: getClass());
258: }
259:
260: public void startElement(String uri, String localName,
261: String qName, Attributes attrs) {
262: charData.setLength(0);
263: for (int i = 0; i < attrs.getLength(); i++) {
264: String name = attrs.getQName(i);
265: String value = attrs.getValue(i);
266: attribute(name, value);
267: }
268: }
269:
270: private void attribute(String aname, String value) {
271: if (aname.equals("X"))
272: config.x = Integer.parseInt(value);
273: else if (aname.equals("Y"))
274: config.y = Integer.parseInt(value);
275: else if (aname.equals("WIDTH"))
276: config.width = Integer.parseInt(value);
277: else if (aname.equals("HEIGHT"))
278: config.height = Integer.parseInt(value);
279: else if (aname.equals("EXT_STATE"))
280: config.extState = Integer.parseInt(value);
281: else if (aname.equals("PLAIN"))
282: config.plainView = ("TRUE".equals(value));
283: else if (aname.equals("TOP"))
284: config.top = value;
285: else if (aname.equals("LEFT"))
286: config.left = value;
287: else if (aname.equals("BOTTOM"))
288: config.bottom = value;
289: else if (aname.equals("RIGHT"))
290: config.right = value;
291: else if (aname.equals("TOP_POS"))
292: config.topPos = Integer.parseInt(value);
293: else if (aname.equals("LEFT_POS"))
294: config.leftPos = Integer.parseInt(value);
295: else if (aname.equals("BOTTOM_POS"))
296: config.bottomPos = Integer.parseInt(value);
297: else if (aname.equals("RIGHT_POS"))
298: config.rightPos = Integer.parseInt(value);
299: else if (aname.equals("AUTORELOAD"))
300: autoReload = value;
301: else if (aname.equals("AUTORELOAD_DIALOG"))
302: autoReloadDialog = value;
303: }
304:
305: /**
306: * @return true if the uri points to a remote file
307: */
308: public static boolean skipRemote(String uri) {
309: if (jEdit.getBooleanProperty("restore.remote"))
310: return false;
311: if (MiscUtilities.isURL(uri)) {
312: String protocol = MiscUtilities.getProtocolOfURL(uri);
313: if (!protocol.equals("file"))
314: return true;
315: }
316: return false;
317: }
318:
319: public void endElement(String uri, String localName, String name) {
320: if (name.equals("BUFFER")) {
321: if (restoreFiles && !skipRemote(charData.toString())) {
322: currentBuffer = jEdit.openFile(null, charData
323: .toString());
324: // if the autoReload attributes are not present, don't set anything
325: // it's sufficient to check whether they are present on the first BUFFER element
326: if (currentBuffer != null) {
327: if (autoReload != null)
328: currentBuffer.setAutoReload("TRUE"
329: .equals(autoReload));
330: if (autoReloadDialog != null)
331: currentBuffer.setAutoReloadDialog("TRUE"
332: .equals(autoReloadDialog));
333: }
334: }
335: } else if (name.equals("PANES"))
336: config.splitConfig = charData.toString();
337: else if (name.equals("VIEW")) {
338: view = jEdit.newView(view, null, config);
339: config = new View.ViewConfig();
340: }
341: }
342:
343: public void characters(char[] ch, int start, int length) {
344: charData.append(ch, start, length);
345: }
346: } //}}}
347:
348: //}}}
349: }
|