KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > gjt > sp > jedit > EditPlugin


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 JavaDoc;
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 <i>className</i> 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>className</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 will not work with
50  * jEdit 4.3final.
51  * </li>
52  * <li><code>plugin.<i>className</i>.name</code></li>
53  * <li><code>plugin.<i>className</i>.version</code></li>
54  * <li><code>plugin.<i>className</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  * <li><code>plugin.<i>className</i>.description</code> - the short description
59  * associated with the plugin. The short description is used by the Plugin
60  * Manager and on the list pages on Plugin Central. </li>
61  * </ul>
62  *
63  * The following properties are optional but recommended:
64  *
65  * <ul>
66  * <li><code>plugin.<i>className</i>.author</code></li>
67  * <li><code>plugin.<i>className</i>.docs</code> - the path to plugin
68  * documentation in HTML format. </li>
69  * <li><code>plugin.<i>className</i>.longdescription</code> - the path to
70  * the long description in XHTML (no fancy stuff here, please - just proper
71  * XHTML subset with the basic tags: <tt>html, h1, h2, p, li, ul, ol, a href,b ,i, u, br/ </tt>)
72  * <p> The long description is extracted from the plugin at various times,
73  * primarily at plugin packaging time to update the data on the
74  * plugin detail pages of Plugin Central. </p>
75  * <p>
76  * If this property is left out, the default will be to look in a file
77  * called &lt;description.html&gt;. </p>
78  *</li>
79  *</ul>
80  *<p>
81  * For the previous two properties, if a relative path is supplied,
82  * it should be both </p>
83  * <ol>
84  * <li> relative to the location of the .props file (when it is in the source tree) </li>
85  * <li> relative to the root of the JAR (when it is packaged in the JAR file) </li>
86  *</ol>
87  *
88  *<p> Both conditions are easily satisfied if the .props file as well as
89  * description.html are both located in the root directory of the plugin,
90  * as well as the generated JAR. </p>
91  *
92  * <h3>Plugin dependency properties</h3>
93  *
94  * <p>Plugin dependencies are also specified using properties.
95  * Each dependency is defined in a property named with
96  * <code>plugin.<i>className</i>.depend.</code> followed by a number.
97  * Dependencies must be numbered in order, starting from zero.
98  * This determines the order that dependent plugins get loaded and activated,
99  * so order is very important. </p>
100 *
101  * <p> The value of a dependency property has one of the following forms: </p>
102  *
103  * <ul>
104  * <li> <code>jdk <i>minimumJavaVersion</i></code> </li>
105  * <li> <code>jedit <i>minimumjEditVersion</i></code> - note that this must be
106  * a version number in the form returned by {@link jEdit#getBuild()},
107  * not {@link jEdit#getVersion()}. Note that the documentation here describes
108  * the jEdit 4.2 plugin API, so this dependency must be set to at least
109  * <code>04.02.99.00</code> (4.2final).</li>
110  * <li><code><i>pluginClassName pluginVersion</i></code> - the fully quailified
111  * plugin class name with package must be specified.</li>
112  * <li><code>optional plugin <i>pluginClassName pluginVersion</i></code> -
113  * an optional dependency, indicating that the plugin will work without it,
114  * but that the dependency should be loaded before this plugin. </li>
115 </ul>
116
117  <p>In this example, the ProjectViewer plugin is an optional dependency of
118  the Console, beacause the Console only listens to events from the ProjectViewer.
119  It requires Jedit 4.2 final. </p>
120
121 <pre>
122 plugin.console.ConsolePlugin.depend.0=jedit 04.02.99.00
123 plugin.console.ConsolePlugin.depend.1=jdk 1.5
124 plugin.console.ConsolePlugin.depend.2=plugin errorlist.ErrorListPlugin 1.4
125 plugin.console.ConsolePlugin.depend.3=optional plugin projectviewer.ProjectPlugin 2.1.0.92
126 </pre>
127
128  * <h3>Plugin menu item properties</h3>
129  *
130  *<p> To add your plugin to the view's <b>Plugins</b> menu, define one of these two
131  * properties: </p>
132  *
133  * <ul>
134  * <li><code>plugin.<i>className</i>.menu-item</code> - if this is defined,
135  * the action named by this property is added to the <b>Plugins</b> menu.</li>
136  * <li><code>plugin.<i>className</i>.menu</code> - if this is defined,
137  * a sub-menu is added to the <b>Plugins</b> menu whose content is the
138  * whitespace-separated list of action names in this property. A separator may
139  * be added to the sub-menu by listing <code>-</code> in the property.</li>
140  * </ul>
141  *
142  * <p>If you want the plugin's menu items to be determined at runtime, define a
143  * property <code>plugin.<i>className</i>.menu.code</code> to be BeanShell
144  * code that evaluates to an implementation of
145  * {@link org.gjt.sp.jedit.menu.DynamicMenuProvider}.</p>
146  *<p>
147  * To add your plugin to the file system browser's <b>Plugins</b> menu, define
148  * one of these two properties:
149  *</p>
150  * <ul>
151  * <li><code>plugin.<i>className</i>.browser-menu-item</code> - if this is
152  * defined, the action named by this property is added to the <b>Plugins</b>
153  * menu.</li>
154  * <li><code>plugin.<i>className</i>.browser-menu</code> - if this is defined,
155  * a sub-menu is added to the <b>Plugins</b> menu whose content is the
156  * whitespace-separated list of action names in this property. A separator may
157  * be added to the sub-menu by listing <code>-</code> in the property.</li>
158  * </ul>
159  *
160  *<p> In all cases, each action's
161  * menu item label is taken from the <code><i>actionName</i>.label</code>
162  * property. View actions are defined in an <code>actions.xml</code>
163  * file, file system browser actions are defined in a
164  * <code>browser.actions.xml</code> file; see {@link ActionSet}.
165  *</p>
166  * <h3>Plugin option pane properties</h3>
167  *
168  * <p>To add your plugin to the <b>Plugin Options</b> dialog box, define one of
169  * these two properties:
170  *</p>
171  * <ul>
172  * <li><code>plugin.<i>className</i>.option-pane=<i>paneName</i></code> - if this is defined,
173  * a single option pane with this name is added to the <b>Plugin Options</b>
174  * menu.</li>
175  * <li><code>plugin.<i>className</i>.option-group=<i>paneName1</i> [<i>paneName2 paneName3</i> ...]</code> - if this is defined,
176  * a branch node is added to the <b>Plugin Options</b> dialog box whose content
177  * is the whitespace-separated list of <i>paneNames</i> in this property.</li>
178  * </ul>
179  *
180  * Then for each option <i>paneName</i>, define these two properties:
181  *
182  * <ul>
183  * <li><code>options.<i>paneName</i>.label</code> - the label to show
184  * for the pane in the dialog box.</li>
185  * <li><code>options.<i>paneName</i>.code</code> - BeanShell code that
186  * evaluates to an instance of the {@link OptionPane} class.</li>
187  *
188  * <h3>Example</h3>
189  *
190  * Here is an example set of plugin properties:
191  *
192  * <pre>plugin.QuickNotepadPlugin.activate=defer
193  *plugin.QuickNotepadPlugin.name=QuickNotepad
194  *plugin.QuickNotepadPlugin.author=John Gellene
195  *plugin.QuickNotepadPlugin.version=4.2
196  *plugin.QuickNotepadPlugin.docs=QuickNotepad.html
197  *plugin.QuickNotepadPlugin.depend.0=jedit 04.02.01.00
198  *plugin.QuickNotepadPlugin.menu=quicknotepad \
199  * - \
200  * quicknotepad.choose-file \
201  * quicknotepad.save-file \
202  * quicknotepad.copy-to-buffer
203  *plugin.QuickNotepadPlugin.option-pane=quicknotepad
204  *
205  * plugin.QuickNotepadPlugin.option-pane=quicknotepad
206  * options.quicknotepad.code=new QuickNotepadOptionPane();
207  * options.quicknotepad.label=QuickNotepad
208  * options.quicknotepad.file=File:
209  * options.quicknotepad.choose-file=Choose
210  * options.quicknotepad.choose-file.title=Choose a notepad file
211  * options.quicknotepad.choose-font=Font:
212  * options.quicknotepad.show-filepath.title=Display notepad file path
213 </pre>
214  *
215  * Note that action and option pane labels are not shown in the above example.
216  *
217  * @see org.gjt.sp.jedit.jEdit#getProperty(String)
218  * @see org.gjt.sp.jedit.jEdit#getPlugin(String)
219  * @see org.gjt.sp.jedit.jEdit#getPlugins()
220  * @see org.gjt.sp.jedit.jEdit#getPluginJAR(String)
221  * @see org.gjt.sp.jedit.jEdit#getPluginJARs()
222  * @see org.gjt.sp.jedit.jEdit#addPluginJAR(String)
223  * @see org.gjt.sp.jedit.jEdit#removePluginJAR(PluginJAR,boolean)
224  * @see org.gjt.sp.jedit.ActionSet
225  * @see org.gjt.sp.jedit.gui.DockableWindowManager
226  * @see org.gjt.sp.jedit.OptionPane
227  * @see org.gjt.sp.jedit.PluginJAR
228  * @see org.gjt.sp.jedit.ServiceManager
229  *
230  * @author Slava Pestov
231  * @author John Gellene (API documentation)
232  * @author Alan Ezust (API documentation)
233  * @since jEdit 2.1pre1
234  */

235 public abstract class EditPlugin
236 {
237     //{{{ start() method
238
/**
239      * jEdit calls this method when the plugin is being activated, either
240      * during startup or at any other time. A plugin can get activated for
241      * a number of reasons:
242      *
243      * <ul>
244      * <li>The plugin is written for jEdit 4.1 or older, in which case it
245      * will always be loaded at startup.</li>
246      * <li>The plugin has its <code>activate</code> property set to
247      * <code>startup</code>, in which case it will always be loaded at
248      * startup.</li>
249      * <li>One of the properties listed in the plugin's
250      * <code>activate</code> property is set to <code>true</code>,
251      * in which case it will always be loaded at startup.</li>
252      * <li>One of the plugin's classes is being accessed by another plugin,
253      * a macro, or a BeanShell snippet in a plugin API XML file.</li>
254      * </ul>
255      *
256      * Note that this method is always called from the event dispatch
257      * thread, even if the activation resulted from a class being loaded
258      * from another thread. A side effect of this is that some of your
259      * plugin's code might get executed before this method finishes
260      * running.<p>
261      *
262      * When this method is being called for plugins written for jEdit 4.1
263      * and below, no views or buffers are open. However, this is not the
264      * case for plugins using the new API. For example, if your plugin adds
265      * tool bars to views, make sure you correctly handle the case where
266      * views are already open when the plugin is loaded.<p>
267      *
268      * If your plugin must be loaded on startup, take care to have this
269      * method return as quickly as possible.<p>
270      *
271      * The default implementation of this method does nothing.
272      *
273      * @since jEdit 2.1pre1
274      */

275     public void start() {}
276     //}}}
277

278     //{{{ stop() method
279
/**
280      * jEdit calls this method when the plugin is being unloaded. This can
281      * be when the program is exiting, or at any other time.<p>
282      *
283      * If a plugin uses state information or other persistent data
284      * that should be stored in a special format, this would be a good place
285      * to write the data to storage. If the plugin uses jEdit's properties
286      * API to hold settings, no special processing is needed for them on
287      * exit, since they will be saved automatically.<p>
288      *
289      * With plugins written for jEdit 4.1 and below, this method is only
290      * called when the program is exiting. However, this is not the case
291      * for plugins using the new API. For example, if your plugin adds
292      * tool bars to views, make sure you correctly handle the case where
293      * views are still open when the plugin is unloaded.<p>
294      *
295      * To avoid memory leaks, this method should ensure that no references
296      * to any objects created by this plugin remain in the heap. In the
297      * case of actions, dockable windows and services, jEdit ensures this
298      * automatically. For other objects, your plugin must clean up maually.
299      * <p>
300      *
301      * The default implementation of this method does nothing.
302      *
303      * @since jEdit 2.1pre1
304      */

305     public void stop() {} //}}}
306

307     /**
308      * Returns true if the plugin uses the standard plugin home
309      *
310      * @return true if the plugin stores it's datas in the folder given by {@link #getPluginHome()}
311      * default is false
312      * @since 4.3pre9
313      */

314     public boolean usePluginHome()
315     {
316         return false;
317     }
318
319     //{{{ getPluginHome() method
320
/**
321      * Returns the home of your plugin.
322      *
323      * @return the home of your plugin. It can be null if there is no settings directory
324      * @since 4.3pre9
325      */

326     public final String JavaDoc getPluginHome()
327     {
328         return pluginHome;
329     } //}}}
330

331     //{{{ getClassName() method
332
/**
333      * Returns the plugin's class name. This might not be the same as
334      * the class of the actual <code>EditPlugin</code> instance, for
335      * example if the plugin is not loaded yet.
336      *
337      * @since jEdit 2.5pre3
338      */

339     public String JavaDoc getClassName()
340     {
341         return getClass().getName();
342     } //}}}
343

344     //{{{ getPluginJAR() method
345
/**
346      * Returns the JAR file containing this plugin.
347      * @since jEdit 4.2pre1
348      */

349     public PluginJAR getPluginJAR()
350     {
351         return jar;
352     } //}}}
353

354     //{{{ createMenuItems() method
355
/**
356      * Called by the view when constructing its <b>Plugins</b> menu.
357      * See the description of this class for details about how the
358      * menu items are constructed from plugin properties.
359      *
360      * @since jEdit 4.2pre1
361      */

362     public final JMenuItem JavaDoc createMenuItems()
363     {
364         if(this instanceof Broken)
365             return null;
366
367         String JavaDoc menuItemName = jEdit.getProperty("plugin." +
368             getClassName() + ".menu-item");
369         if(menuItemName != null)
370             return GUIUtilities.loadMenuItem(menuItemName);
371
372         String JavaDoc menuProperty = "plugin." + getClassName() + ".menu";
373         String JavaDoc codeProperty = "plugin." + getClassName() + ".menu.code";
374         if(jEdit.getProperty(menuProperty) != null
375             || jEdit.getProperty(codeProperty) != null)
376         {
377             String JavaDoc pluginName = jEdit.getProperty("plugin." +
378                 getClassName() + ".name");
379             return new EnhancedMenu(menuProperty,pluginName);
380         }
381
382         return null;
383     } //}}}
384

385     //{{{ createBrowserMenuItems() method
386
/**
387      * Called by the filesystem browser when constructing its
388      * <b>Plugins</b> menu.
389      * See the description of this class for details about how the
390      * menu items are constructed from plugin properties.
391      *
392      * @since jEdit 4.2pre1
393      */

394     public final JMenuItem JavaDoc createBrowserMenuItems()
395     {
396         if(this instanceof Broken)
397             return null;
398
399         String JavaDoc menuItemName = jEdit.getProperty("plugin." +
400             getClassName() + ".browser-menu-item");
401         if(menuItemName != null)
402         {
403             return GUIUtilities.loadMenuItem(
404                 VFSBrowser.getActionContext(),
405                 menuItemName,
406                 false);
407         }
408
409         String JavaDoc menuProperty = "plugin." + getClassName() + ".browser-menu";
410         if(jEdit.getProperty(menuProperty) != null)
411         {
412             String JavaDoc pluginName = jEdit.getProperty("plugin." +
413                 getClassName() + ".name");
414             return new EnhancedMenu(menuProperty,pluginName,
415                 VFSBrowser.getActionContext());
416         }
417
418         return null;
419     } //}}}
420

421     //{{{ Deprecated methods
422

423     //{{{ createMenuItems() method
424
/**
425      * @deprecated Instead of overriding this method, define properties
426      * as specified in the description of this class.
427      */

428     public void createMenuItems(Vector menuItems) {} //}}}
429

430     //{{{ createOptionPanes() method
431
/**
432      * @deprecated Instead of overriding this method, define properties
433      * as specified in the description of this class.
434      */

435     public void createOptionPanes(OptionsDialog optionsDialog) {} //}}}
436

437     //}}}
438

439     //{{{ Package-private members
440
PluginJAR jar;
441     /**
442      * This is the plugin home path. Please never access it directly and use
443      * {@link #getPluginHome()} instead
444      */

445     String JavaDoc pluginHome;
446     //}}}
447

448     //{{{ Broken class
449
/**
450      * A placeholder for a plugin that didn't load.
451      * @see jEdit#getPlugin(String)
452      * @see PluginJAR#getPlugin()
453      * @see PluginJAR#activatePlugin()
454      */

455     public static class Broken extends EditPlugin
456     {
457         public String JavaDoc getClassName()
458         {
459             return clazz;
460         }
461
462         // package-private members
463
Broken(PluginJAR jar, String JavaDoc clazz)
464         {
465             this.jar = jar;
466             this.clazz = clazz;
467         }
468
469         // private members
470
private String JavaDoc clazz;
471     } //}}}
472

473     //{{{ Deferred class
474
/**
475      * A placeholder for a plugin that hasn't been loaded yet.
476      * @see jEdit#getPlugin(String)
477      * @see PluginJAR#getPlugin()
478      * @see PluginJAR#activatePlugin()
479      */

480     public static class Deferred extends EditPlugin
481     {
482         public String JavaDoc getClassName()
483         {
484             return clazz;
485         }
486
487         // package-private members
488
Deferred(PluginJAR jar, String JavaDoc clazz)
489         {
490             this.jar = jar;
491             this.clazz = clazz;
492         }
493
494         EditPlugin loadPluginClass()
495         {
496             return null;
497         }
498
499         public String JavaDoc toString()
500         {
501             return "Deferred[" + clazz + "]";
502         }
503
504         // private members
505
private String JavaDoc clazz;
506     } //}}}
507
}
508
Popular Tags