PageRenderTime 174ms CodeModel.GetById 155ms app.highlight 15ms RepoModel.GetById 2ms app.codeStats 0ms

/jEdit/tags/jedit-4-5-pre1/org/gjt/sp/jedit/PerspectiveManager.java

#
Java | 379 lines | 270 code | 42 blank | 67 comment | 60 complexity | 4da7afeb1537a032e2cfffaf4951bed4 MD5 | raw file
  1/*
  2 * PerspectiveManager.java - Saves view configuration
  3 * :tabSize=8:indentSize=8:noTabs=false:
  4 * :folding=explicit:collapseFolds=1:
  5 *
  6 * Copyright (C) 2003 Slava Pestov
  7 *
  8 * This program is free software; you can redistribute it and/or
  9 * modify it under the terms of the GNU General Public License
 10 * as published by the Free Software Foundation; either version 2
 11 * of the License, or any later version.
 12 *
 13 * This program is distributed in the hope that it will be useful,
 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16 * GNU General Public License for more details.
 17 *
 18 * You should have received a copy of the GNU General Public License
 19 * along with this program; if not, write to the Free Software
 20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 21 */
 22
 23package org.gjt.sp.jedit;
 24
 25import java.io.StreamTokenizer;
 26import java.io.StringReader;
 27import java.io.IOException;
 28import java.util.Collection;
 29import java.util.LinkedList;
 30import java.util.Stack;
 31
 32import org.gjt.sp.util.IOUtilities;
 33import org.gjt.sp.util.Log;
 34import org.gjt.sp.util.XMLUtilities;
 35import org.xml.sax.Attributes;
 36import org.xml.sax.InputSource;
 37import org.xml.sax.helpers.DefaultHandler;
 38
 39/**
 40 * Manages persistence of open buffers and views across jEdit sessions.
 41 * @since jEdit 4.2pre1
 42 * @author Slava Pestov
 43 * @version $Id: PerspectiveManager.java 20108 2011-10-18 12:16:38Z evanpw $
 44 */
 45public class PerspectiveManager
 46{
 47	private static final String PERSPECTIVE_FILENAME = "perspective";
 48
 49	//{{{ isPerspectiveDirty() method
 50	/**
 51	 * We only autosave the perspective if it has changed, to avoid spinning
 52	 * up the disk on laptops.
 53	 * @since jEdit 4.2pre13
 54	 */
 55	public static boolean isPerspectiveDirty()
 56	{
 57		return dirty;
 58	} //}}}
 59
 60	//{{{ setPerspectiveDirty() method
 61	/**
 62	 * We only autosave the perspective if it has changed, to avoid spinning
 63	 * up the disk on laptops.
 64	 * @since jEdit 4.2pre13
 65	 */
 66	public static void setPerspectiveDirty(boolean dirty)
 67	{
 68		PerspectiveManager.dirty = dirty;
 69	} //}}}
 70
 71	//{{{ isPerspectiveEnabled() method
 72	/**
 73	 * We disable saving of the perspective while the 'close all' dialog is
 74	 * showing.
 75	 * @since jEdit 4.3pre2
 76	 */
 77	public static boolean isPerspectiveEnabled()
 78	{
 79		return enabled;
 80	} //}}}
 81
 82	//{{{ setPerspectiveEnabled() method
 83	/**
 84	 * We disable saving of the perspective while the 'close all' dialog is
 85	 * showing.
 86	 * @since jEdit 4.3pre2
 87	 */
 88	public static void setPerspectiveEnabled(boolean enabled)
 89	{
 90		PerspectiveManager.enabled = enabled;
 91	} //}}}
 92
 93	//{{{ loadPerspective() method
 94	public static View loadPerspective(boolean restoreFiles)
 95	{
 96		if(perspectiveXML == null)
 97			return null;
 98
 99		if(!perspectiveXML.fileExists())
100			return null;
101
102		Log.log(Log.MESSAGE,PerspectiveManager.class,"Loading " + perspectiveXML);
103
104		PerspectiveHandler handler = new PerspectiveHandler(restoreFiles);
105		try
106		{
107			perspectiveXML.load(handler);
108		}
109		catch(IOException e)
110		{
111			Log.log(Log.ERROR,PerspectiveManager.class,e);
112		}
113		return handler.view;
114	} //}}}
115
116	//{{{ savePerspective() method
117	public static void savePerspective(boolean autosave)
118	{
119		if(!isPerspectiveEnabled() || !jEdit.isStartupDone())
120			return;
121
122		if(perspectiveXML == null)
123			return;
124		
125		// backgrounded
126		if(jEdit.getBufferCount() == 0)
127			return;
128
129		Buffer[] buffers = jEdit.getBuffers();
130		Collection<Buffer> savedBuffers = new LinkedList<Buffer>();
131		for (Buffer buffer: buffers)
132		{
133			if (!buffer.isNewFile())
134			{
135				savedBuffers.add(buffer);
136			}
137		}
138
139		if(!autosave)
140			Log.log(Log.MESSAGE,PerspectiveManager.class,"Saving " + perspectiveXML);
141
142		String lineSep = System.getProperty("line.separator");
143
144		SettingsXML.Saver out = null;
145
146		try
147		{
148			out = perspectiveXML.openSaver();
149			out.writeXMLDeclaration();
150
151			out.write("<!DOCTYPE PERSPECTIVE SYSTEM \"perspective.dtd\">");
152			out.write(lineSep);
153			out.write("<PERSPECTIVE>");
154			out.write(lineSep);
155
156			for (Buffer buffer: savedBuffers)
157			{
158				out.write("<BUFFER AUTORELOAD=\"");
159				out.write(buffer.getAutoReload() ? "TRUE" : "FALSE");
160				out.write("\" AUTORELOAD_DIALOG=\"");
161				out.write(buffer.getAutoReloadDialog() ? "TRUE" : "FALSE");
162				out.write("\">");
163				out.write(XMLUtilities.charsToEntities(buffer.getPath(), false));
164				out.write("</BUFFER>");
165				out.write(lineSep);
166			}
167
168			View[] views = jEdit.getViews();
169			for(int i = 0; i < views.length; i++)
170			{
171				View view = views[i];
172				// ensures that active view is saved last,
173				// ie created last on next load, ie in front
174				// on next load
175				if(view == jEdit.getActiveView()
176					&& i != views.length - 1)
177				{
178					View last = views[views.length - 1];
179					views[i] = last;
180					views[views.length - 1] = view;
181					view = last;
182				}
183
184				View.ViewConfig config = views[i].getViewConfig();
185				out.write("<VIEW PLAIN=\"");
186				out.write(config.plainView ? "TRUE" : "FALSE");
187				out.write("\">");
188				out.write(lineSep);
189				
190				if (config.title != null)
191				{
192					out.write(lineSep);
193					out.write("<TITLE>");
194					out.write(XMLUtilities.charsToEntities(config.title,false));
195					out.write("</TITLE>");
196					out.write(lineSep);
197				}
198
199				out.write("<PANES>");
200				out.write(lineSep);
201				out.write(XMLUtilities.charsToEntities(
202					config.splitConfig,false));
203				out.write(lineSep);
204				out.write("</PANES>");
205				out.write(lineSep);
206
207				out.write("<GEOMETRY X=\"");
208				out.write(String.valueOf(config.x));
209				out.write("\" Y=\"");
210				out.write(String.valueOf(config.y));
211				out.write("\" WIDTH=\"");
212				out.write(String.valueOf(config.width));
213				out.write("\" HEIGHT=\"");
214				out.write(String.valueOf(config.height));
215				out.write("\" EXT_STATE=\"");
216				out.write(String.valueOf(config.extState));
217				out.write("\" />");
218				out.write(lineSep);
219
220				if (config.docking != null)
221					config.docking.saveLayout(PERSPECTIVE_FILENAME, i);
222				
223				out.write("</VIEW>");
224				out.write(lineSep);
225			}
226
227			out.write("</PERSPECTIVE>");
228			out.write(lineSep);
229
230			out.finish();
231		}
232		catch(IOException io)
233		{
234			Log.log(Log.ERROR,PerspectiveManager.class,"Error saving " + perspectiveXML);
235			Log.log(Log.ERROR,PerspectiveManager.class,io);
236		}
237		finally
238		{
239			IOUtilities.closeQuietly(out);
240		}
241	} //}}}
242
243	//{{{ Private members
244	private static boolean dirty, enabled = true;
245	private static SettingsXML perspectiveXML;
246	//}}}
247
248	//{{{ Class initializer
249	static
250	{
251		String settingsDirectory = jEdit.getSettingsDirectory();
252		if(settingsDirectory != null)
253		{
254			perspectiveXML = new SettingsXML(settingsDirectory, PERSPECTIVE_FILENAME);
255		}
256	} //}}}
257
258	//{{{ PerspectiveHandler class
259	private static class PerspectiveHandler extends DefaultHandler
260	{
261		View view;
262		private StringBuilder charData;
263		View.ViewConfig config;
264		boolean restoreFiles;
265		boolean restoreSplits;
266		String autoReload, autoReloadDialog;
267		
268		PerspectiveHandler(boolean restoreFiles)
269		{
270			this.restoreFiles = restoreFiles;
271			restoreSplits = jEdit.getBooleanProperty("restore.splits", true);
272			config = new View.ViewConfig();
273			charData = new StringBuilder();
274			config.docking = View.getDockingFrameworkProvider().createDockingLayout();
275		}
276
277		@Override
278		public InputSource resolveEntity(String publicId, String systemId)
279		{
280			return XMLUtilities.findEntity(systemId, "perspective.dtd", getClass());
281		}
282
283		@Override
284		public void startElement(String uri, String localName,
285					 String qName, Attributes attrs)
286		{
287			charData.setLength(0);
288			for (int i = 0; i < attrs.getLength(); i++)
289			{
290				String name = attrs.getQName(i);
291				String value = attrs.getValue(i);
292				attribute(name, value);
293			}
294		}
295
296		private void attribute(String aname, String value)
297		{
298			if(aname.equals("X"))
299				config.x = Integer.parseInt(value);
300			else if(aname.equals("Y"))
301				config.y = Integer.parseInt(value);
302			else if(aname.equals("WIDTH"))
303				config.width = Integer.parseInt(value);
304			else if(aname.equals("HEIGHT"))
305				config.height = Integer.parseInt(value);
306			else if(aname.equals("EXT_STATE"))
307				config.extState = Integer.parseInt(value);
308			else if(aname.equals("PLAIN"))
309				config.plainView = ("TRUE".equals(value));
310			else if(aname.equals("AUTORELOAD"))
311				autoReload = value;
312			else if(aname.equals("AUTORELOAD_DIALOG"))
313				autoReloadDialog = value;
314		}
315
316		/**
317		 * @return true if the uri points to a remote file
318		 */
319		public static boolean skipRemote(String uri)
320		{
321			if (jEdit.getBooleanProperty("restore.remote"))
322				return false;
323			if(MiscUtilities.isURL(uri))
324			{
325				String protocol = MiscUtilities.getProtocolOfURL(uri);
326				if (!protocol.equals("file")) return true;
327			}
328			return false;
329		}
330
331		@Override
332		public void endElement(String uri, String localName, String name)
333		{
334			if(name.equals("BUFFER"))
335			{
336				if (restoreFiles && !skipRemote(charData.toString()))
337				{
338					Buffer restored = jEdit.openTemporary(null,null, charData.toString(), false);
339					// if the autoReload attributes are not present, don't set anything
340					// it's sufficient to check whether they are present on the first BUFFER element
341					if (restored != null)
342					{
343						if(autoReload != null)
344							restored.setAutoReload("TRUE".equals(autoReload));
345						if(autoReloadDialog != null)
346							restored.setAutoReloadDialog("TRUE".equals(autoReloadDialog));
347						jEdit.commitTemporary(restored);
348					}
349				}
350			}
351			else if(name.equals("PANES"))
352			{
353				SplitConfigParser parser = new SplitConfigParser(charData.toString());
354				parser.setIncludeSplits(restoreSplits);
355				parser.setIncludeFiles(restoreFiles);
356				parser.setIncludeRemoteFiles(jEdit.getBooleanProperty("restore.remote"));
357				config.splitConfig = parser.parse();
358			}
359			else if(name.equals("VIEW"))
360			{
361				if (config.docking != null)
362					config.docking.loadLayout(PERSPECTIVE_FILENAME, jEdit.getViewCount());
363				view = jEdit.newView(view,null,config);
364				config = new View.ViewConfig();
365				config.docking = View.getDockingFrameworkProvider().createDockingLayout();
366			}
367			else if(name.equals("TITLE"))
368				config.title = charData.toString();
369		}
370
371		@Override
372		public void characters(char[] ch, int start, int length)
373		{
374			charData.append(ch,start,length);
375		}
376		
377	}
378	//}}}
379}