PageRenderTime 26ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-2-pre14/org/gjt/sp/jedit/EditPlugin.java

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