📄 dockablewindowmanager.java
字号:
/* * DockableWindowManager.java - manages dockable windows * :tabSize=8:indentSize=8:noTabs=false: * :folding=explicit:collapseFolds=1: * * Copyright (C) 2000, 2004 Slava Pestov * * 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 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. */package org.gjt.sp.jedit.gui;//{{{ Imports import bsh.*; import com.microstar.xml.*; import javax.swing.*; import java.awt.event.*; import java.awt.*; import java.io.*; import java.net.URL; import java.util.*; import org.gjt.sp.jedit.msg.*; import org.gjt.sp.jedit.*; import org.gjt.sp.util.Log;//}}}/** * The <code>DockableWindowManager</code> keeps track of dockable windows. * Each {@link org.gjt.sp.jedit.View} has an instance of this class.<p> * * <b>dockables.xml:</b><p> * * Dockable window definitions are read from <code>dockables.xml</code> files * contained inside plugin JARs. A dockable definition file has the following * form: * * <pre><?xml version="1.0"?> *<!DOCTYPE DOCKABLES SYSTEM "dockables.dtd"> *<DOCKABLES> * <DOCKABLE NAME="name"> * // Code to create the dockable * </DOCKABLE> *</DOCKABLES></pre> * * More than one <code><DOCKABLE><code> tag may be present. The code that * creates the dockable can reference any BeanShell built-in variable * (see {@link org.gjt.sp.jedit.BeanShell}), along with a variable * <code>position</code> whose value is one of * {@link #FLOATING}, {@link #TOP}, {@link #LEFT}, {@link #BOTTOM}, * and {@link #RIGHT}.<p> * * The following properties must be defined for each dockable window: * * <ul> * <li><code><i>name</i>.title</code> - the string to show in the title bar * of the dockable.</li> * <li><code><i>name</i>.label</code> - the dockable's menu item label.</li> * </ul> * * A number of actions are automatically created for each dockable window: * * <ul> * <li><code><i>name</i></code> - opens the dockable window.</li> * <li><code><i>name</i>-toggle</code> - toggles the dockable window's visibility.</li> * <li><code><i>name</i>-float</code> - opens the dockable window in a new * floating window.</li> * </ul> * * Note that only the first action needs a <code>label</code> property, the * rest have automatically-generated labels. * * <b>Implementation details:</b><p> * * When an instance of this class is initialized by the {@link org.gjt.sp.jedit.View} * class, it * iterates through the list of registered dockable windows (from jEdit itself, * and any loaded plugins) and * examines options supplied by the user in the <b>Global * Options</b> dialog box. Any plugins designated for one of the * four docking positions are displayed.<p> * * To create an instance of a dockable window, the <code>DockableWindowManager</code> * finds and executes the BeanShell code extracted from the appropriate * <code>dockables.xml</code> file. This code will typically consist of a call * to the constructor of the dockable window component. The result of the * BeanShell expression, typically a newly constructed component, is placed * in a window managed by this class. * * @see org.gjt.sp.jedit.View#getDockableWindowManager() * * @author Slava Pestov * @author John Gellene (API documentation) * @version $Id: DockableWindowManager.java,v 1.95 2004/03/19 22:42:21 spestov Exp $ * @since jEdit 2.6pre3 */public class DockableWindowManager extends JPanel implements EBComponent{ //{{{ Static part of class //{{{ Constants /** * Floating position. * @since jEdit 2.6pre3 */ public static final String FLOATING = "floating"; /** * Top position. * @since jEdit 2.6pre3 */ public static final String TOP = "top"; /** * Left position. * @since jEdit 2.6pre3 */ public static final String LEFT = "left"; /** * Bottom position. * @since jEdit 2.6pre3 */ public static final String BOTTOM = "bottom"; /** * Right position. * @since jEdit 2.6pre3 */ public static final String RIGHT = "right"; //}}} //{{{ loadDockableWindows() method /** * Plugins shouldn't need to call this method. * @since jEdit 4.2pre1 */ public static void loadDockableWindows(PluginJAR plugin, URL uri, PluginJAR.PluginCacheEntry cache) { Reader in = null; try { Log.log(Log.DEBUG,DockableWindowManager.class, "Loading dockables from " + uri); DockableListHandler dh = new DockableListHandler(plugin,uri); in = new BufferedReader( new InputStreamReader( uri.openStream())); XmlParser parser = new XmlParser(); parser.setHandler(dh); parser.parse(null, null, in); if(cache != null) { cache.cachedDockableNames = dh.getCachedDockableNames(); cache.cachedDockableActionFlags = dh.getCachedDockableActionFlags(); } } catch(XmlException xe) { int line = xe.getLine(); String message = xe.getMessage(); Log.log(Log.ERROR,DockableWindowManager.class,uri + ":" + line + ": " + message); } catch(Exception e) { Log.log(Log.ERROR,DockableWindowManager.class,e); } finally { try { if(in != null) in.close(); } catch(IOException io) { Log.log(Log.ERROR,DockableWindowManager.class,io); } } } //}}} //{{{ unloadDockableWindows() method /** * Plugins shouldn't need to call this method. * @since jEdit 4.2pre1 */ public static void unloadDockableWindows(PluginJAR plugin) { Iterator entries = dockableWindowFactories.entrySet().iterator(); while(entries.hasNext()) { Map.Entry entry = (Map.Entry)entries.next(); Factory factory = (Factory)entry.getValue(); if(factory.plugin == plugin) entries.remove(); } } //}}} //{{{ cacheDockableWindows() method /** * @since jEdit 4.2pre1 */ public static void cacheDockableWindows(PluginJAR plugin, String[] name, boolean[] actions) { for(int i = 0; i < name.length; i++) { Factory factory = new Factory(plugin, name[i],null,actions[i]); dockableWindowFactories.put(name[i],factory); } } //}}} //{{{ registerDockableWindow() method public static void registerDockableWindow(PluginJAR plugin, String name, String code, boolean actions) { Factory factory = (Factory)dockableWindowFactories.get(name); if(factory != null) { factory.code = code; factory.loaded = true; } else { factory = new Factory(plugin,name,code,actions); dockableWindowFactories.put(name,factory); } } //}}} //{{{ getRegisteredDockableWindows() method public static String[] getRegisteredDockableWindows() { String[] retVal = new String[dockableWindowFactories.size()]; Iterator entries = dockableWindowFactories.values().iterator(); int i = 0; while(entries.hasNext()) { Factory factory = (Factory)entries.next(); retVal[i++] = factory.name; } return retVal; } //}}} //{{{ DockableListHandler class static class DockableListHandler extends HandlerBase { //{{{ DockableListHandler constructor DockableListHandler(PluginJAR plugin, URL uri) { this.plugin = plugin; this.uri = uri; stateStack = new Stack(); actions = true; cachedDockableNames = new LinkedList(); cachedDockableActionFlags = new LinkedList(); } //}}} //{{{ resolveEntity() method public Object resolveEntity(String publicId, String systemId) { if("dockables.dtd".equals(systemId)) { // this will result in a slight speed up, since we // don't need to read the DTD anyway, as AElfred is // non-validating return new StringReader("<!-- -->"); /* try { return new BufferedReader(new InputStreamReader( getClass().getResourceAsStream ("/org/gjt/sp/jedit/dockables.dtd"))); } catch(Exception e) { Log.log(Log.ERROR,this,"Error while opening" + " dockables.dtd:"); Log.log(Log.ERROR,this,e); } */ } return null; } //}}} //{{{ attribute() method public void attribute(String aname, String value, boolean isSpecified) { aname = (aname == null) ? null : aname.intern(); value = (value == null) ? null : value.intern(); if(aname == "NAME") dockableName = value; else if(aname == "NO_ACTIONS") actions = (value == "FALSE"); } //}}} //{{{ doctypeDecl() method public void doctypeDecl(String name, String publicId, String systemId) throws Exception { if("DOCKABLES".equals(name)) return; Log.log(Log.ERROR,this,uri + ": DOCTYPE must be DOCKABLES"); } //}}} //{{{ charData() method public void charData(char[] c, int off, int len) { String tag = peekElement(); String text = new String(c, off, len); if (tag == "DOCKABLE") { code = text; } } //}}} //{{{ startElement() method public void startElement(String tag) { tag = pushElement(tag); } //}}} //{{{ endElement() method public void endElement(String name) { if(name == null) return; String tag = peekElement(); if(name.equals(tag)) { if(tag == "DOCKABLE") { registerDockableWindow(plugin, dockableName,code,actions); cachedDockableNames.add(dockableName); cachedDockableActionFlags.add( new Boolean(actions)); // make default be true for the next // action actions = true; } popElement(); } else { // can't happen throw new InternalError(); } } //}}} //{{{ startDocument() method public void startDocument() { try { pushElement(null); } catch (Exception e) { e.printStackTrace(); } } //}}} //{{{ getCachedDockableNames() method public String[] getCachedDockableNames() { return (String[])cachedDockableNames.toArray(new String[cachedDockableNames.size()]); } //}}} //{{{ getCachedDockableActionFlags() method public boolean[] getCachedDockableActionFlags() { boolean[] returnValue = new boolean[ cachedDockableActionFlags.size()]; Iterator iter = cachedDockableActionFlags.iterator(); int i = 0; while(iter.hasNext()) { boolean flag = ((Boolean)iter.next()) .booleanValue(); returnValue[i++] = flag; } return returnValue; } //}}} //{{{ Private members //{{{ Instance variables private PluginJAR plugin; private URL uri; private java.util.List cachedDockableNames; private java.util.List cachedDockableActionFlags; private String dockableName; private String code; private boolean actions; private Stack stateStack; //}}} //{{{ pushElement() method private String pushElement(String name) { name = (name == null) ? null : name.intern(); stateStack.push(name); return name; } //}}} //{{{ peekElement() method private String peekElement() { return (String) stateStack.peek(); } //}}} //{{{ popElement() method private String popElement() { return (String) stateStack.pop(); } //}}} //}}} } //}}} //{{{ Factory class static class Factory { PluginJAR plugin; String name; String code; boolean loaded; //{{{ Factory constructor Factory(PluginJAR plugin, String name, String code, boolean actions) { this.plugin = plugin; this.name = name; this.code = code; if(code != null) loaded = true; if(actions) { ActionSet actionSet = (plugin == null ? jEdit.getBuiltInActionSet() : plugin.getActionSet()); actionSet.addAction(new OpenAction(name));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -