Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/gjt/sp/jedit/EditPlugin.java


1   /*
2    * EditPlugin.java - Abstract class all plugins must implement
3    * :tabSize=8:indentSize=8:noTabs=false:
4    * :folding=explicit:collapseFolds=1:
5    *
6    * Copyright (C) 1999, 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  
23  package org.gjt.sp.jedit;
24  
25  import javax.swing.JMenuItem;
26  import java.util.*;
27  import org.gjt.sp.jedit.browser.VFSBrowser;
28  import org.gjt.sp.jedit.gui.OptionsDialog;
29  import org.gjt.sp.jedit.menu.EnhancedMenu;
30  
31  /**
32   * The abstract base class that every plugin must implement.
33   * Alternatively, instead of extending this class, a plugin core class can
34   * extend {@link EBPlugin} to automatically receive EditBus messages.
35   *
36   * <h3>Basic plugin information properties</h3>
37   *
38   * Note that in all cases above where a class name is needed, the fully
39   * qualified class name, including the package name, if any, must be used.<p>
40   *
41   * The following properties are required for jEdit to load the plugin:
42   *
43   * <ul>
44   * <li><code>plugin.<i>class name</i>.activate</code> - set this to
45   * <code>defer</code> if your plugin only needs to be loaded when it is first
46   * invoked; set it to <code>startup</code> if your plugin must be loaded at
47   * startup regardless; set it to a whitespace-separated list of property names
48   * if your plugin should be loaded if at least one of these properties is set.
49   * Note that if this property is <b>not</b> set, the plugin is loaded like an
50   * old-style jEdit 4.1 plugin.
51   * </li>
52   * <li><code>plugin.<i>class name</i>.name</code></li>
53   * <li><code>plugin.<i>class name</i>.version</code></li>
54   * <li><code>plugin.<i>class name</i>.jars</code> - only needed if your plugin
55   * bundles external JAR files. Contains a whitespace-separated list of JAR
56   * file names. Without this property, the plugin manager will leave behind the
57   * external JAR files when removing the plugin.</li>
58   * </ul>
59   *
60   * The following properties are optional but recommended:
61   *
62   * <ul>
63   * <li><code>plugin.<i>class name</i>.author</code></li>
64   * <li><code>plugin.<i>class name</i>.docs</code> - the path to plugin
65   * documentation in HTML format within the JAR file.</li>
66   * </ul>
67   *
68   * <h3>Plugin dependency properties</h3>
69   *
70   * Plugin dependencies are also specified using properties.
71   * Each dependency is defined in a property named with
72   * <code>plugin.<i>class name</i>.depend.</code> followed by a number.
73   * Dependencies must be numbered in order, starting from zero.<p>
74   *
75   * The value of a dependency property has one of the following forms:
76   *
77   * <ul>
78   * <li><code>jdk <i>minimum Java version</i></code></li>
79   * <li><code>jedit <i>minimum jEdit version</i></code> - note that this must be
80   * a version number in the form returned by {@link jEdit#getBuild()},
81   * not {@link jEdit#getVersion()}. Note that the documentation here describes
82   * the jEdit 4.2 plugin API, so this dependency must be set to at least
83   * <code>04.02.01.00</code>.</li>
84   * <li><code>plugin <i>plugin</i> <i>version</i></code> - the fully quailified
85   * plugin class name must be specified.</li>
86   * </ul>
87   *
88   * <h3>Plugin menu item properties</h3>
89   *
90   * To add your plugin to the view's <b>Plugins</b> menu, define one of these two
91   * properties:
92   *
93   * <ul>
94   * <li><code>plugin.<i>class name</i>.menu-item</code> - if this is defined,
95   * the action named by this property is added to the <b>Plugins</b> menu.</li>
96   * <li><code>plugin.<i>class name</i>.menu</code> - if this is defined,
97   * a sub-menu is added to the <b>Plugins</b> menu whose content is the
98   * whitespace-separated list of action names in this property. A separator may
99   * be added to the sub-menu by listing <code>-</code> in the property.</li>
100  * </ul>
101  *
102  * If you want the plugin's menu items to be determined at runtime, define a
103  * property <code>plugin.<i>class name</i>.menu.code</code> to be BeanShell
104  * code that evaluates to an implementation of
105  * {@link org.gjt.sp.jedit.menu.DynamicMenuProvider}.<p>
106  *
107  * To add your plugin to the file system browser's <b>Plugins</b> menu, define
108  * one of these two properties:
109  *
110  * <ul>
111  * <li><code>plugin.<i>class name</i>.browser-menu-item</code> - if this is
112  * defined, the action named by this property is added to the <b>Plugins</b>
113  * menu.</li>
114  * <li><code>plugin.<i>class name</i>.browser-menu</code> - if this is defined,
115  * a sub-menu is added to the <b>Plugins</b> menu whose content is the
116  * whitespace-separated list of action names in this property. A separator may
117  * be added to the sub-menu by listing <code>-</code> in the property.</li>
118  * </ul>
119  *
120  * In all cases, each action's
121  * menu item label is taken from the <code><i>action name</i>.label</code>
122  * property. View actions are defined in an <code>actions.xml</code>
123  * file, file system browser actions are defined in a
124  * <code>browser.actions.xml</code> file; see {@link ActionSet}.
125  *
126  * <h3>Plugin option pane properties</h3>
127  *
128  * To add your plugin to the <b>Plugin Options</b> dialog box, define one of
129  * these two properties:
130  *
131  * <ul>
132  * <li><code>plugin.<i>class name</i>.option-pane</code> - if this is defined,
133  * the option pane named by this property is added to the <b>Plugin Options</b>
134  * menu.</li>
135  * <li><code>plugin.<i>class name</i>.option-group</code> - if this is defined,
136  * a branch node is added to the <b>Plugin Options</b> dialog box whose content
137  * is the whitespace-separated list of option pane names in this property.</li>
138  * </ul>
139  *
140  * Then for each option pane name, define these two properties:
141  *
142  * <ul>
143  * <li><code>options.<i>option pane name</i>.label</code> - the label to show
144  * for the pane in the dialog box.</li>
145  * <li><code>options.<i>option pane name</i>.code</code> - BeanShell code that
146  * evaluates to an instance of the {@link OptionPane} class.</li>
147  *
148  * <h3>Example</h3>
149  *
150  * Here is an example set of plugin properties:
151  *
152  * <pre>plugin.QuickNotepadPlugin.activate=defer
153  *plugin.QuickNotepadPlugin.name=QuickNotepad
154  *plugin.QuickNotepadPlugin.author=John Gellene
155  *plugin.QuickNotepadPlugin.version=4.2
156  *plugin.QuickNotepadPlugin.docs=QuickNotepad.html
157  *plugin.QuickNotepadPlugin.depend.0=jedit 04.02.01.00
158  *plugin.QuickNotepadPlugin.menu=quicknotepad \
159  *    - \
160  *    quicknotepad.choose-file \
161  *    quicknotepad.save-file \
162  *    quicknotepad.copy-to-buffer
163  *plugin.QuickNotepadPlugin.option-pane=quicknotepad</pre>
164  *
165  * Note that action and option pane labels are not shown in the above example.
166  *
167  * @see org.gjt.sp.jedit.jEdit#getProperty(String)
168  * @see org.gjt.sp.jedit.jEdit#getPlugin(String)
169  * @see org.gjt.sp.jedit.jEdit#getPlugins()
170  * @see org.gjt.sp.jedit.jEdit#getPluginJAR(String)
171  * @see org.gjt.sp.jedit.jEdit#getPluginJARs()
172  * @see org.gjt.sp.jedit.jEdit#addPluginJAR(String)
173  * @see org.gjt.sp.jedit.jEdit#removePluginJAR(PluginJAR,boolean)
174  * @see org.gjt.sp.jedit.ActionSet
175  * @see org.gjt.sp.jedit.gui.DockableWindowManager
176  * @see org.gjt.sp.jedit.OptionPane
177  * @see org.gjt.sp.jedit.PluginJAR
178  * @see org.gjt.sp.jedit.ServiceManager
179  *
180  * @author Slava Pestov
181  * @author John Gellene (API documentation)
182  * @version $Id: EditPlugin.java,v 1.31 2003/05/03 20:34:25 spestov Exp $
183  * @since jEdit 2.1pre1
184  */
185 public abstract class EditPlugin
186 {
187   //{{{ start() method
188   /**
189    * jEdit calls this method when the plugin is being activated, either
190    * during startup or at any other time. A plugin can get activated for
191    * a number of reasons:
192    *
193    * <ul>
194    * <li>The plugin is written for jEdit 4.1 or older, in which case it
195    * will always be loaded at startup.</li>
196    * <li>The plugin has its <code>activate</code> property set to
197    * <code>startup</code>, in which case it will always be loaded at
198    * startup.</li>
199    * <li>One of the properties listed in the plugin's
200    * <code>activate</code> property is set to <code>true</code>,
201    * in which case it will always be loaded at startup.</li>
202    * <li>One of the plugin's classes is being accessed by another plugin,
203    * a macro, or a BeanShell snippet in a plugin API XML file.</li>
204    * </ul>
205    *
206    * Note that this method is always called from the event dispatch
207    * thread, even if the activation resulted from a class being loaded
208    * from another thread. A side effect of this is that some of your
209    * plugin's code might get executed before this method finishes
210    * running.<p>
211    *
212    * When this method is being called for plugins written for jEdit 4.1
213    * and below, no views or buffers are open. However, this is not the
214    * case for plugins using the new API. For example, if your plugin adds
215    * tool bars to views, make sure you correctly handle the case where
216    * views are already open when the plugin is loaded.<p>
217    *
218    * If your plugin must be loaded on startup, take care to have this
219    * method return as quickly as possible.<p>
220    *
221    * The default implementation of this method does nothing.
222    *
223    * @since jEdit 2.1pre1
224    */
225   public void start() {}
226   //}}}
227 
228   //{{{ stop() method
229   /**
230    * jEdit calls this method when the plugin is being unloaded. This can
231    * be when the program is exiting, or at any other time.<p>
232    *
233    * If a plugin uses state information or other persistent data
234    * that should be stored in a special format, this would be a good place
235    * to write the data to storage.  If the plugin uses jEdit's properties
236    * API to hold settings, no special processing is needed for them on
237    * exit, since they will be saved automatically.<p>
238    *
239    * With plugins written for jEdit 4.1 and below, this method is only
240    * called when the program is exiting. However, this is not the case
241    * for plugins using the new API. For example, if your plugin adds
242    * tool bars to views, make sure you correctly handle the case where
243    * views are still open when the plugin is unloaded.<p>
244    *
245    * To avoid memory leaks, this method should ensure that no references
246    * to any objects created by this plugin remain in the heap. In the
247    * case of actions, dockable windows and services, jEdit ensures this
248    * automatically. For other objects, your plugin must clean up maually.
249    * <p>
250    *
251    * The default implementation of this method does nothing.
252    *
253    * @since jEdit 2.1pre1
254    */
255   public void stop() {} //}}}
256 
257   //{{{ getClassName() method
258   /**
259    * Returns the plugin's class name. This might not be the same as
260    * the class of the actual <code>EditPlugin</code> instance, for
261    * example if the plugin is not loaded yet.
262    *
263    * @since jEdit 2.5pre3
264    */
265   public String getClassName()
266   {
267     return getClass().getName();
268   } //}}}
269 
270   //{{{ getPluginJAR() method
271   /**
272    * Returns the JAR file containing this plugin.
273    * @since jEdit 4.2pre1
274    */
275   public PluginJAR getPluginJAR()
276   {
277     return jar;
278   } //}}}
279 
280   //{{{ createMenuItems() method
281   /**
282    * Called by the view when constructing its <b>Plugins</b> menu.
283    * See the description of this class for details about how the
284    * menu items are constructed from plugin properties.
285    *
286    * @since jEdit 4.2pre1
287    */
288   public final JMenuItem createMenuItems()
289   {
290     if(this instanceof Broken)
291       return null;
292 
293     String menuItemName = jEdit.getProperty("plugin." +
294       getClassName() + ".menu-item");
295     if(menuItemName != null)
296       return GUIUtilities.loadMenuItem(menuItemName);
297 
298     String menuProperty = "plugin." + getClassName() + ".menu";
299     String codeProperty = "plugin." + getClassName() + ".menu.code";
300     if(jEdit.getProperty(menuProperty) != null
301       || jEdit.getProperty(codeProperty) != null)
302     {
303       String pluginName = jEdit.getProperty("plugin." +
304         getClassName() + ".name");
305       return new EnhancedMenu(menuProperty,pluginName);
306     }
307 
308     return null;
309   } //}}}
310 
311   //{{{ createBrowserMenuItems() method
312   /**
313    * Called by the filesystem browser when constructing its
314    * <b>Plugins</b> menu.
315    * See the description of this class for details about how the
316    * menu items are constructed from plugin properties.
317    *
318    * @since jEdit 4.2pre1
319    */
320   public final JMenuItem createBrowserMenuItems()
321   {
322     if(this instanceof Broken)
323       return null;
324 
325     String menuItemName = jEdit.getProperty("plugin." +
326       getClassName() + ".browser-menu-item");
327     if(menuItemName != null)
328     {
329       return GUIUtilities.loadMenuItem(
330         VFSBrowser.getActionContext(),
331         menuItemName,
332         false);
333     }
334 
335     String menuProperty = "plugin." + getClassName() + ".browser-menu";
336     if(jEdit.getProperty(menuProperty) != null)
337     {
338       String pluginName = jEdit.getProperty("plugin." +
339         getClassName() + ".name");
340       return new EnhancedMenu(menuProperty,pluginName,
341         VFSBrowser.getActionContext());
342     }
343 
344     return null;
345   } //}}}
346 
347   //{{{ Deprecated methods
348 
349   //{{{ createMenuItems() method
350   /**
351    * @deprecated Instead of overriding this method, define properties
352    * as specified in the description of this class.
353    */
354   public void createMenuItems(Vector menuItems) {} //}}}
355 
356   //{{{ createOptionPanes() method
357   /**
358    * @deprecated Instead of overriding this method, define properties
359    * as specified in the description of this class.
360    */
361   public void createOptionPanes(OptionsDialog optionsDialog) {} //}}}
362 
363   //{{{ getJAR() method
364   /**
365    * @deprecated Call <code>getPluginJAR()</code> instead.
366    */
367   public EditPlugin.JAR getJAR()
368   {
369     return jar;
370   } //}}}
371 
372   //}}}
373 
374   //{{{ Package-private members
375   EditPlugin.JAR jar;
376   //}}}
377 
378   //{{{ Broken class
379   /**
380    * A placeholder for a plugin that didn't load.
381    * @see jEdit#getPlugin(String)
382    * @see PluginJAR#getPlugin()
383    * @see PluginJAR#activatePlugin()
384    */
385   public static class Broken extends EditPlugin
386   {
387     public String getClassName()
388     {
389       return clazz;
390     }
391 
392     // package-private members
393     Broken(String clazz)
394     {
395       this.clazz = clazz;
396     }
397 
398     // private members
399     private String clazz;
400   } //}}}
401 
402   //{{{ Deferred class
403   /**
404    * A placeholder for a plugin that hasn't been loaded yet.
405    * @see jEdit#getPlugin(String)
406    * @see PluginJAR#getPlugin()
407    * @see PluginJAR#activatePlugin()
408    */
409   public static class Deferred extends EditPlugin
410   {
411     public String getClassName()
412     {
413       return clazz;
414     }
415 
416     // package-private members
417     Deferred(String clazz)
418     {
419       this.clazz = clazz;
420     }
421 
422     EditPlugin loadPluginClass()
423     {
424       return null;
425     }
426 
427     public String toString()
428     {
429       return "Deferred[" + clazz + "]";
430     }
431 
432     // private members
433     private String clazz;
434   } //}}}
435 
436   //{{{ JAR class
437   /**
438    * @deprecated Use <code>PluginJAR</code> instead.
439    */
440   public static class JAR extends PluginJAR
441   {
442     JAR(java.io.File file)
443     {
444       super(file);
445     }
446   }
447   //}}}
448 }