PageRenderTime 100ms CodeModel.GetById 77ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 0ms

/jEdit/tags/jedit-4-1-pre5/doc/users-guide/host-design.xml

#
XML | 1009 lines | 875 code | 116 blank | 18 comment | 0 complexity | 6fd63ab2b1e8fb10099c9736bf764960 MD5 | raw file
   1<!-- jEdit 4.0 Plugin Guide, (C) 2001, 2002 John Gellene            -->
   2
   3<!-- jEdit buffer-local properties:                           -->
   4<!-- :indentSize=1:tabSize=2:noTabs=true:maxLineLen=72:       -->
   5
   6<!-- This file contains a discussion of the host architecture -->
   7<!-- in the jEdit Plugin API                                  -->
   8<!-- $Id: host-design.xml 4174 2002-05-19 08:31:14Z spestov $
   9-->
  10
  11<chapter id="host-design"><title>jEdit as a Plugin Host</title>
  12
  13<para>
  14	A good way to start learning what a plugin requires is to look at what
  15  the host application does with one. We start our discussion of
  16  plugins by outlining how jEdit loads and displays them. This section
  17  only provides a broad overview of the more important components that
  18  make up jEdit; specifics of the API will be documented in
  19  subsequent chapters.
  20</para>
  21
  22<sect1 id="host-design-load"><title>
  23<indexterm>
  24	<primary>Plugin API</primary>
  25	<secondary>loading at startup</secondary>
  26</indexterm>
  27Loading Plugins</title>
  28
  29<para>
  30  As part of its startup routine, jEdit's <function>main</function>
  31  method calls various methods to load and initialize plugins.
  32  This occurs after the application has done the following:
  33</para>
  34
  35  <itemizedlist>
  36    <listitem><para>
  37      parsed command line options;
  38    </para></listitem>
  39    <listitem><para>
  40      started the edit server (unless instructed not to do so
  41      by a command line option) and;
  42    </para></listitem>
  43    <listitem><para>
  44      loaded application properties, any user-supplied properties, and the
  45      application's set of actions that will be available from jEdit's menu
  46      bar (as well as the toolbar and keyboard shortcuts);
  47    </para></listitem>
  48  </itemizedlist>
  49
  50<para>
  51  Plugin loading occurs before jEdit creates any windows or loads any files
  52  for editing. It also occurs before jEdit runs any startup scripts.
  53</para>
  54
  55<sect2 id="host-design-loader"><title>
  56<indexterm>
  57	<primary>JAR class loader</primary>
  58</indexterm>
  59The JARClassLoader</title>
  60
  61<para>
  62  Plugins are loaded from files with the <filename>.jar</filename>
  63  filename extension located in the <filename>jars</filename>
  64  subdirectories of the jEdit installation and user settings directories
  65  (see <xref linkend="settings-directory" />).
  66</para>
  67
  68<para>
  69  For each JAR archive file it finds, jEdit creates an instance of the
  70  <classname>JARClassLoader</classname> class. This is a jEdit-specific
  71  class
  72  that implements the Java platform's abstract class
  73  <classname>ClassLoader</classname>. The constructor for the
  74  <classname>JARClassLoader</classname> object does the following:
  75    <itemizedlist>
  76      <listitem><para>
  77        Reads action definitions from any file named
  78        <filename>actions.xml</filename> in the archive (the file need
  79        not be at the top level). See <xref
  80        linkend="resources-action" />.
  81      </para></listitem>
  82      <listitem><para>
  83        Parses and loads the contents of any file named
  84        <filename>dockables.xml</filename> in the archive (the file need
  85        not be at the top level). This file contains BeanShell code for
  86        creating docking or floating windows that will contain the visible
  87        components of the plugin.  Not all plugins define dockable
  88        windows,
  89        but those that do need a <filename>dockables.xml</filename> file.
  90        See <xref linkend="resources-dockables" />.
  91      </para></listitem>
  92      <listitem><para>
  93        Loads any properties defined in files ending with
  94        the extension <filename>.props</filename> that are contained
  95        in the archive. See <xref linkend="resources-properties" />.
  96      </para></listitem>
  97      <listitem><para>
  98        Adds any class file with a name ending with
  99        <filename>Plugin.class</filename> to an internal collection of
 100        plugin class names maintained by the
 101        <classname>JARClassLoader</classname>. See <xref
 102        linkend="class-editplugin" />.
 103      </para></listitem>
 104      <listitem><para>
 105       Adds to a collection maintained by jEdit a new object of
 106       type <classname>EditPlugin.JAR</classname>. This is a data structure
 107       holding the name of the JAR archive file, a reference to the
 108       <classname>JARClassLoader</classname> and a collection,
 109       initially empty, of plugins found in the archive file.
 110      </para></listitem>
 111    </itemizedlist>
 112</para>
 113
 114<para>
 115  Once all JAR files have been examined for the above resources,
 116  jEdit initializes all class files whose names end in
 117  <filename>Plugin.class</filename>, as identified in the first pass
 118  through the JAR archive.  We will call these classes
 119<indexterm>
 120	<primary>Plugin API</primary>
 121	<secondary>plugin core class</secondary>
 122</indexterm>
 123<firstterm>plugin core classes</firstterm>. They provide
 124  the principal point of contact between jEdit and the plugin. A plugin
 125  core class must extend jEdit's abstract <classname>EditPlugin</classname>
 126  class. Use of a class name ending in <classname>Plugin</classname> is also
 127  required.
 128</para>
 129
 130<para>
 131<indexterm>
 132	<primary>Plugins</primary>
 133	<secondary>dependencies</secondary>
 134</indexterm>
 135  For each plugin core class, the initialization routine first checks the plugin's
 136  properties to see if it is subject to any dependencies. For example, a
 137  plugin may require that the version of the Java runtime environment or
 138  of jEdit itself be equal to or above some threshold version. A plugin
 139  can also require the presence of another plugin or a particular class
 140  from another archive. If any dependency is
 141  not satisfied, the loader marks the plugin as <quote>broken</quote> and
 142  logs an error message.
 143</para>
 144
 145<para>
 146  If all dependencies are satisfied, a new instance
 147  of the plugin core class is created and added to the collection
 148  maintained by the appropriate <classname>EditPlugin.JAR</classname>
 149  object. By accessing that object, jEdit can keep track of plugins it has
 150  successfully loaded, and call methods or perform routines on them.
 151</para>
 152
 153<sidebar><title>
 154<indexterm>
 155	<primary>Plugin API</primary>
 156	<secondary>using class libraries</secondary>
 157</indexterm>
 158Additional class libraries for plugins</title>
 159
 160<para>
 161  JAR files with no plugin core classes are also loaded by jEdit; no special
 162  initialization is performed on them, and the classes they contain are
 163  made available to other plugins.  For example, many plugins that rely on
 164  third-party class libraries ship them as separate JAR archives.  The libraries
 165  will be available inside the jEdit environment but are not part of a general
 166  classpath or library collection when running other Java applications.
 167</para>
 168
 169<para>
 170  A plugin that bundles extra JAR archives must define a property that
 171  lists these JAR files in order for the plugin manager to be able to
 172  remove the plugin completely. See <xref
 173  linkend="resources-properties" />.
 174</para>
 175
 176</sidebar>
 177
 178</sect2>
 179
 180<sect2 id="host-design-plugin-start"><title>Starting the Plugin</title>
 181
 182<para>
 183  After creating and storing the plugin core object, jEdit calls the
 184  <function>start()</function> method of the plugin core class.
 185  The <function>start()</function> method can perform initialization of the
 186  object's data members.
 187  Because this method is defined as an empty <quote>no-op</quote> in the
 188  <classname>EditPlugin</classname> abstract class, a plugin need not
 189  provide an implementation if no unique initialization is required.
 190</para>
 191
 192</sect2>
 193
 194<sect2 id="class-editplugin"><title>The EditPlugin Class</title>
 195
 196<para>
 197  Recall that this abstract class is the base for every plugin core
 198  class.  Its methods
 199  provide for basic interaction between the plugin and jEdit. The class
 200  has four methods which are called by jEdit at various times. None of
 201  these methods are required to be implemented, but most plugins will
 202  override at least one.
 203</para>
 204
 205<itemizedlist>
 206
 207  <listitem>
 208    <funcsynopsis>
 209      <funcprototype>
 210        <funcdef>public void <function>start</function></funcdef>
 211        <paramdef></paramdef>
 212      </funcprototype>
 213    </funcsynopsis>
 214    <para>
 215      The jEdit startup routine calls this method for each loaded
 216      plugin.  Plugins typically use this method to register information
 217      with the EditBus and perform other initialization.
 218    </para>
 219  </listitem>
 220
 221  <listitem>
 222    <funcsynopsis>
 223      <funcprototype>
 224        <funcdef>public void <function>stop</function></funcdef>
 225        <paramdef></paramdef>
 226      </funcprototype>
 227    </funcsynopsis>
 228    <para>
 229      When jEdit is exiting, it calls this method on each plugin. If a
 230      plugin uses or creates state information or other persistent data
 231      that should be stored in a special format, this would be a good place to write
 232      the data to storage.  If you use jEdit's properties API to hold
 233      <quote>key-value</quote> type settings for your plugins, no special
 234      processing is needed for them, since jEdit loads application
 235      properties automatically at startup and writes them to the
 236      <filename>properties</filename> file in the user's settings directory
 237      when the application exits.  Most plugins find this approach sufficient for
 238      saving settings.
 239    </para>
 240  </listitem>
 241
 242  <listitem>
 243    <funcsynopsis>
 244      <funcprototype>
 245        <funcdef>public void <function>createMenuItems</function></funcdef>
 246        <paramdef>Vector <parameter>menuItems</parameter></paramdef>
 247      </funcprototype>
 248    </funcsynopsis>
 249    <para>
 250      When a <classname>View</classname> object is created, it calls this
 251      method on each plugin core class to obtain entries to be displayed
 252      in the view's <guimenu>Plugins</guimenu> menu. The
 253      <parameter>menuItems</parameter> parameter is a
 254      <classname>Vector</classname> that accumulates menu items and
 255      menus as it is passed from plugin to plugin.
 256    </para>
 257    <para>
 258      While jEdit does not require a plugin to supply menu items, a plugin's
 259      usefulness would be extremely limited without them. The easiest way to
 260      provide menu items is to
 261      package them as entries in the plugin's property
 262      file and implement <function>createMenuItems()</function> with a
 263      call to jEdit's <function>GUIUtilities.loadMenu()</function>
 264      method. The following code illustrates this approach:
 265    </para>
 266<informalexample><programlisting>public void createMenuItems(Vector menuItems)
 267{
 268    menuItems.addElement(GUIUtilities.loadMenu(
 269        "myplugin.menu"));
 270}</programlisting></informalexample>
 271
 272    <para>
 273      The parameter passed to <function>loadMenu()</function> is
 274      the name of a property defined in the plugin's own property file that
 275      contains menu data.  The form of the property entry is a list of labels
 276      that in turn correspond to other property names and ultimately to
 277      the actual text for menu items as well as implementation code. We will
 278      detail the format of the menu data in <xref linkend="plugin-implement-menu"/>
 279    </para>
 280
 281    <para>
 282      The <function>GUIUtilities.loadMenuItem()</function> method is also
 283      available for plugins that only wish to add a single menu item to
 284      the <guimenu>Plugins</guimenu> menu. The parameter names a property
 285      that points to label text in the plugin's properties file and
 286      implementing code in the plugin's <filename>actions.xml</filename>
 287      file.
 288    </para>
 289  </listitem>
 290
 291  <listitem>
 292    <funcsynopsis>
 293      <funcprototype>
 294        <funcdef>public void <function>createOptionPanes</function></funcdef>
 295        <paramdef>OptionsDialog <parameter>dialog</parameter></paramdef>
 296      </funcprototype>
 297    </funcsynopsis>
 298    <para>
 299      This method is called for each plugin during the creation of
 300      the <guilabel>Global Options</guilabel> dialog box.
 301      To show an option pane, the plugin should define an
 302      option pane class and implement <function>createOptionPane()</function>
 303      as follows:
 304    </para>
 305<informalexample><programlisting>dialog.addOptionPane(new MyPluginOptionPane());</programlisting></informalexample>
 306    <para>
 307      Plugins can also define more than one option pane, grouped in an
 308      <quote>option group</quote>.
 309      <!-- We will discuss the design and elements of the option pane API
 310      in <xref linkend="api-option-classes"/>. -->
 311    </para>
 312  </listitem>
 313
 314</itemizedlist>
 315
 316<para>
 317 This class defines two other methods which may be useful to some
 318 plugins or for debugging purposes.  They are fully implemented
 319 in the parent class and used mainly by jEdit's core code.
 320</para>
 321
 322<itemizedlist>
 323
 324  <listitem>
 325    <funcsynopsis>
 326      <funcprototype>
 327        <funcdef>public String <function>getClassName</function></funcdef>
 328        <void/>
 329      </funcprototype>
 330    </funcsynopsis>
 331    <para>
 332      This shortcut method returns <function>getClass().getName()</function>.
 333    </para>
 334  </listitem>
 335
 336  <listitem>
 337    <funcsynopsis>
 338      <funcprototype>
 339        <funcdef>public EditPlugin.JAR <function>getJAR</function></funcdef>
 340        <void/>
 341      </funcprototype>
 342    </funcsynopsis>
 343    <para>
 344      This method returns the <classname>EditPlugin.JAR</classname> data
 345      object associated with the plugin.
 346    </para>
 347  </listitem>
 348
 349</itemizedlist>
 350
 351</sect2>
 352
 353</sect1>
 354
 355<sect1 id="host-design-resources"><title>Plugin Resources</title>
 356
 357
 358
 359<sect2 id="resources-properties"><title>Plugin Properties</title>
 360
 361<para>
 362  jEdit maintains a list of <quote>properties</quote>, which are
 363  name/value pairs used to store human-readable strings, user settings,
 364  and various other forms of meta-data. During startup, jEdit loads the
 365  default set of properties, followed by plugin properties stored in
 366  plugin JAR files, finally followed by user properties. Plugins can
 367  access properties from all three sources.
 368</para>
 369
 370<para>
 371  Property files contained in plugin JARs must end with the filename
 372  extension <filename>.props</filename>, and have a very simple syntax,
 373  which the following example illustrates:
 374</para>
 375
 376<informalexample><programlisting># Lines starting with '#' are ignored.
 377name=value
 378another.name=another value
 379long.property=Long property value, split over \
 380    several lines
 381escape.property=Newlines and tabs can be inserted \
 382    using the \t and \n escapes
 383backslash.property=A backslash can be inserted by writing \\.</programlisting>
 384</informalexample>
 385
 386<para>
 387  The following types of plugin information
 388  are supplied using properties:
 389</para>
 390
 391<itemizedlist>
 392  <listitem>
 393    <para>
 394      Information regarding the name, author, and version of the plugin.
 395      This information is required. Here is an example:
 396    </para>
 397    <informalexample><programlisting>plugin.MyPlugin.name=My Plugin
 398plugin.MyPlugin.author=Jay Edit
 399plugin.MyPlugin.version=1.0.3</programlisting></informalexample>
 400    <para>
 401      Note that each property is prefixed with
 402      <literal>plugin.</literal>, followed by the fully qualified name
 403      of the plugin core class (including a package name, if there is
 404      one).
 405    </para>
 406  </listitem>
 407  <listitem>
 408    <para>
 409      Identification of any dependencies the plugin may have on a
 410      particular version of a Java runtime environment, the jEdit
 411      application, or other plugins.
 412    </para>
 413    <para>
 414      Each dependency is defined in a property prefixed with
 415      <literal>plugin.<replaceable>class name</replaceable>.depend.</literal>,
 416      followed by a number. Dependencies must be numbered in order,
 417      starting from zero.
 418    </para>
 419    <para>
 420      The value of a dependency property is one of the words
 421      <literal>jdk</literal>, <literal>jedit</literal>,
 422      or <literal>plugin</literal>,
 423      followed by a Java version number, a jEdit build number, 
 424      or plugin class name and plugin version number,
 425      respectively.
 426    </para>
 427    <para>
 428      Here are some examples:
 429    </para>
 430    <informalexample><programlisting>plugin.MyPlugin.depend.0=jdk 1.4
 431plugin.MyPlugin.depend.1=jedit 04.00.99.00
 432plugin.MyPlugin.depend.2=plugin console.ConsolePlugin 3.2.1</programlisting>
 433</informalexample>
 434
 435  </listitem>
 436
 437  <listitem>
 438    <para>
 439      A list of external class library JARs shipped with the plugin.
 440      If your plugin bundles extra JARs, this property is required
 441      for the plugin manager to be able to remove the plugin completely.
 442    </para>
 443    <para>
 444      The property is a space-separated list of filenames. Here is an
 445      example:
 446    </para>
 447    <informalexample><programlisting>plugin.xslt.XSLTPlugin.jars=xml-apis.jar xalan.jar</programlisting></informalexample>
 448  </listitem>
 449
 450  <listitem>
 451    <para>
 452      Labels for user actions for inclusion in menus and option panes
 453      relating to toolbars and keyboard shortcuts.
 454    </para>
 455    <para>
 456      Action labels are defined in properties named by the
 457      action's internal name as specified in the action catalog,
 458      followed by <literal>.label</literal>:
 459    </para>
 460<informalexample><programlisting>myplugin.label=My Plugin
 461myplugin-grok.label=Grok Current Buffer</programlisting>
 462</informalexample>
 463  </listitem>
 464  <listitem>
 465    <para>
 466      The list of menu items contained in plugin menus, if any.
 467    </para>
 468    <para>
 469      This is discussed in detail in <xref
 470      linkend="plugin-implement-menu" />.
 471    </para>
 472  </listitem>
 473  <listitem>
 474    <para>
 475      Labels and other information regarding the controls contained in
 476      the plugin's windows. These properties can be named any way you
 477      like, however take care not to choose names which may conflict
 478      with those in other plugins.
 479    </para>
 480  </listitem>
 481  <listitem>
 482    <para>
 483      The titles of dockable windows, as displayed in a tabbed or
 484      floating container.
 485    </para>
 486    <para>
 487      These labels are specified in properties named by the dockable
 488      window's identifier (as specified in the <filename>dockables.xml</filename>
 489      file, see <xref linkend="resources-dockables"/>),
 490      suffixed with <literal>.title</literal>. For example:
 491    </para>
 492<informalexample><programlisting>quick-notepad.title=QuickNotepad</programlisting>
 493</informalexample>
 494  </listitem>
 495</itemizedlist>
 496
 497</sect2>
 498
 499<sect2 id="resources-action"><title>The Action Catalog</title>
 500<para>
 501  Actions define procedures that can be bound to a menu
 502  item, a toolbar button or a keyboard shortcut. They can perform any
 503  task encompassed in a public method of any class currently loaded in
 504  jEdit, including plugin classes and classes of the host application.
 505  Among other things, they can cause the appearance and disappearance of
 506  plugin windows.
 507</para>
 508
 509<para>
 510  To manage user actions, jEdit maintains a lookup table of actions
 511  using descriptive strings as keys.  The values in the table are
 512  sets of statements written in BeanShell, jEdit's macro scripting
 513  language.  These scripts either direct the action themselves,
 514  delegate to a method in one of the plugin's classes that
 515  encapsulates the action, or do a little of both.  The scripts are
 516  usually short; elaborate action protocols are usually contained in
 517  compiled code, rather than an interpreted macro script, to speed
 518  execution.
 519</para>
 520
 521<para>
 522  Actions are defined by creating an XML file entitled
 523  <filename>actions.xml</filename> and placing it in the plugin JAR
 524  file. A sample action catalog looks like so:
 525</para>
 526
 527<informalexample><programlisting><![CDATA[<!DOCTYPE ACTIONS SYSTEM "actions.dtd">
 528
 529<ACTIONS>
 530    <ACTION NAME="quicknotepad.choose-file">
 531        <CODE>
 532            view.getDockableWindowManager()
 533                .getDockable(QuickNotepadPlugin.NAME).chooseFile();
 534        </CODE>
 535    </ACTION>
 536
 537    <ACTION NAME="quicknotepad.save-file">
 538        <CODE>
 539            view.getDockableWindowManager()
 540                .getDockable(QuickNotepadPlugin.NAME).saveFile();
 541        </CODE>
 542    </ACTION>
 543
 544    <ACTION NAME="quicknotepad.copy-to-buffer">
 545        <CODE>
 546            view.getDockableWindowManager()
 547                .getDockable(QuickNotepadPlugin.NAME).copyToBuffer();
 548        </CODE>
 549    </ACTION>
 550</ACTIONS>]]></programlisting></informalexample>
 551
 552<para>
 553  The defined elements have the following functions:
 554</para>
 555
 556<itemizedlist>
 557  <listitem>
 558    <para>
 559      <varname>ACTIONS</varname> is the top-level element and refers
 560      to the set of actions used by the plugin.
 561    </para>
 562  </listitem>
 563  <listitem>
 564    <para>
 565      An <varname>ACTION</varname> contains the data for a particular action.
 566      It has three attributes: a required <varname>NAME</varname>;
 567      an optional <varname>NO_REPEAT</varname>, which is a flag
 568      indicating whether the action should not be repeated with the
 569      <keycombo><keycap>Control</keycap><keycap>Enter</keycap></keycombo>
 570      command (see <xref linkend="repeat" />); and an optional
 571      <varname>NO_RECORD</varname> which is a a flag indicating whether the
 572      action should be recorded if it is invoked while a user is recording a
 573      macro. The two flag attributes
 574      can have two possible values, <quote>TRUE</quote> or
 575      <quote>FALSE</quote>. In both cases, <quote>FALSE</quote> is the
 576      default if the attribute is not specified.
 577    </para>
 578  </listitem>
 579  <listitem>
 580    <para>
 581      An <varname>ACTION</varname> can have two child elements
 582      within it: a required <varname>CODE</varname> element which
 583      specifies the
 584      BeanShell code that will be executed when the action is invoked,
 585      and an optional <varname>IS_SELECTED</varname> element, used for
 586      checkbox
 587      menu items.  The <varname>IS_SELECTED</varname> element contains
 588      BeanShell code that returns a boolean flag that will
 589      determine the state of the checkbox.
 590    </para>
 591  </listitem>
 592</itemizedlist>
 593
 594<para>
 595 More discussion of the action catalog can be found in <xref
 596 linkend="plugin-implement-actions" />.
 597</para>
 598
 599</sect2>
 600
 601<sect2 id="resources-dockables"><title>The Dockable Definition File</title>
 602
 603<para>
 604  The jEdit Plugin API uses BeanShell to create the top-level visible container
 605  of a plugin's interface.  The BeanShell code is contained in a file named
 606  <filename>dockables.xml</filename>.  It usually is quite short, providing only
 607  a single BeanShell expression used to create a visible plugin window.
 608</para>
 609
 610<para>
 611  The following example from the QuickNotepad plugin illustrates the
 612  requirements of the data file:
 613<informalexample><programlisting>&lt;?xml version="1.0"?&gt;
 614
 615&lt;!DOCTYPE DOCKABLES SYSTEM "dockables.dtd"&gt;
 616
 617&lt;!-- QuickNotepad dockable windows --&gt;
 618
 619&lt;DOCKABLES&gt;
 620    &lt;DOCKABLE NAME="quicknotepad"&gt;
 621        new QuickNotepad(view, position);
 622    &lt;/DOCKABLE&gt;
 623&lt;/DOCKABLES&gt;</programlisting></informalexample>
 624
 625In this example, the <classname>&lt;DOCKABLE&gt;</classname> element has
 626a single attribute, the dockable window's identifier. This attribute is
 627used to key a property where the window title is stored; see
 628<xref linkend="resources-properties"/>.
 629<!--  If the plugin has no user actions,
 630a second, implicit <classname>&lt;NO_ACTIONS&gt;</classname> attribute
 631should be assigned a value of <constant>true</constant>. -->
 632The contents of the <classname>&lt;DOCKABLE&gt;</classname> element itself is a
 633BeanShell expression that constructs a new <classname>QuickNotepad</classname>
 634object.  The <varname>view</varname> and <varname>position</varname> are
 635predefined by the Plugin API as the view in which the plugin window will reside
 636and the docking position of the plugin.
 637
 638</para>
 639
 640</sect2>
 641
 642<sect2 id="resources-help"><title>Plugin Documentation</title>
 643
 644<para>
 645  While not required by the plugin API, a help file is an essential
 646  element of any plugin written for public release. A single web page is
 647  often all that is required. There are no specific requirements on
 648  layout, but because of the design of jEdit's help viewer, the use of
 649  frames should be avoided. Topics that would be useful include
 650  the following:
 651</para>
 652
 653<itemizedlist>
 654  <listitem>
 655    <para>
 656      a description of the purpose of the plugin;
 657    </para>
 658  </listitem>
 659  <listitem>
 660    <para>
 661      an explanation of the type of input the user can supply through its
 662      visible interface (such as mouse action or text entry in controls);
 663    </para>
 664  </listitem>
 665  <listitem>
 666    <para>
 667      a listing of available user actions that can be taken when the
 668      plugin does not have input focus;
 669    </para>
 670  </listitem>
 671  <listitem>
 672    <para>
 673      a summary of configuration options;
 674    </para>
 675  </listitem>
 676  <listitem>
 677    <para>
 678      information on development of the plugin (such as a change log,
 679      a list of <quote>to do</quote> items, and contact information for
 680      the plugin's author); and
 681    </para>
 682  </listitem>
 683  <listitem>
 684    <para>
 685      licensing information, including acknowledgments for any library
 686      software used by the plugin.
 687    </para>
 688  </listitem>
 689</itemizedlist>
 690
 691<para>
 692 The location of the plugin's help file should be stored in the
 693 <literal>plugin.<replaceable>class name</replaceable>.docs</literal>
 694 property.
 695</para>
 696
 697</sect2>
 698
 699</sect1>
 700
 701<sect1 id="host-design-display"><title>The User Interface of a Plugin</title>
 702
 703<para>
 704  <!-- To display a user interface, plugins can either directly extend Java's
 705  <classname>JFrame</classname>, <classname>JDialog</classname>, or
 706  <classname>JWindow</classname> classes, or use jEdit's dockable window
 707  API. Plugin windows are typically defined in classes that are
 708  part of the plugin package but separate from the plugin core
 709  class. -->
 710  To display a user interface, plugins provide a top-level component
 711  derived (directly or indirectly) from the Swing
 712  <classname>JComponent</classname> class.  This component will be
 713  embedded in a docking of floating window created by the Plugin API. It
 714  is typically defined in a class that is part of the plugin package but
 715  separate from the plugin core class (if one exists).
 716</para>
 717
 718<sect2 id="host-display-view"><title>
 719<indexterm>
 720	<primary>View</primary>
 721	<secondary>use in Plugin API</secondary>
 722</indexterm>
 723<indexterm>
 724	<primary>Plugin API</primary>
 725	<secondary>use of View object</secondary>
 726</indexterm>
 727The Role of the View Object</title>
 728
 729<para>
 730  A <classname>View</classname> is jEdit's top-level frame window.
 731  The largest component it contains is an edit pane that in turn contains a
 732  text area that displays a buffer.  A view can have more than one edit pane
 733  in a split window configuration.  The view also contains a menu bar,
 734  an optional toolbar and other window decorations, as well as docked
 735  windows.
 736</para>
 737<para>
 738  The <classname>View</classname> class performs two important operations
 739  dealing with plugins: creating plugin menu items, and managing dockable
 740  windows.
 741</para>
 742
 743<para>
 744<indexterm>
 745	<primary>Plugin API</primary>
 746	<secondary>menu creation</secondary>
 747</indexterm>
 748
 749  When a view is being created, its initialization routine
 750  iterates through the collection of loaded plugins and calls
 751  the <function>createMenuItems()</function> method of
 752  each plugin core class. In the parent class,
 753  <classname>EditPlugin</classname>, this method is an empty
 754  <quote>no-op</quote>.  In order to add items to jEdit's menu bar
 755  under the <guimenu>Plugins</guimenu> menu, the plugin core class must
 756  supply its own version of <function>createMenuItems()</function>.
 757  As we will explain in <xref linkend="class-editplugin"/>,
 758  the typical plugin, instead of creating Java
 759  <classname>JMenu</classname> and <classname>JMenuItem</classname>
 760  objects directly, relies on a wrapper method in a utility class to
 761  create menu entries.
 762</para>
 763
 764<para>
 765  The <classname>View</classname> also creates and initializes a
 766  <classname>DockableWindowManager</classname> object. This object is
 767  responsible for creating, closing and managing dockable windows.
 768  It will be discussed in more detail below.
 769</para>
 770
 771<para>
 772  Finally, the <classname>View</classname>
 773  and <classname>DockableWindowManager</classname>
 774  classes contain a number of methods
 775  that can be called from plugins; see <xref linkend="class-view" />
 776  and <xref linkend="class-dockablewindowmanager" /> for details.
 777</para>
 778
 779</sect2>
 780
 781<sect2 id="host-display-manager">
 782<title>
 783<indexterm>
 784	<primary>Plugin API</primary>
 785	<secondary>DockableWindowManager class</secondary>
 786</indexterm>
 787<indexterm>
 788	<primary>DockableWindowManager</primary>
 789	<secondary>use in Plugin API</secondary>
 790</indexterm>
 791<indexterm>
 792	<primary>Plugin API</primary>
 793	<secondary>creating dockable windows</secondary>
 794</indexterm>
 795The DockableWindowManager</title>
 796
 797<para>
 798  The <classname>DockableWindowManager</classname> in each
 799  <classname>View</classname> object keeps track of docked
 800  and floating windows. When the <classname>View</classname> object
 801  initializes its <classname>DockableWindowManager</classname>, the
 802  manager iterates through the list of registered dockable windows and
 803  examines options supplied by the user in the <guilabel>Global
 804  Options</guilabel> dialog box. It displays any plugins that the user
 805  designated for one of the four docking positions when the corresponding
 806  button a docking pane is selected.
 807</para>
 808
 809<para>
 810  To create an instance of a dockable window, the
 811  <classname>DockableWindowManager</classname> finds and executes the
 812  BeanShell code extracted from the plugin's
 813  <filename>dockables.xml</filename> file during application startup. This
 814  code will typically consist of a call to the constructor of the docking
 815  window component that passes two parameters: the
 816  <classname>View</classname> associated with the docking window
 817  component, and a <classname>String</classname> representing the component's
 818  docking or floating position.  The result of the BeanShell expression,
 819  typically a newly constructed component, is placed inside the
 820  docking or floating window managed by the
 821  <classname>DockableWindowManager</classname>.
 822</para>
 823
 824<para>
 825  Eventually the <classname>DockableWindowManager</classname> destroys
 826  the plugin window, whether docking or floating, in response to user
 827  action or as part of the destruction of the corresponding
 828  <classname>View</classname> object.
 829</para>
 830
 831<para>
 832  With this broad outline of how jEdit behaves as a plugin host in the
 833  background, we will next review the programming elements that make up
 834  a plugin.
 835</para>
 836
 837</sect2>
 838
 839</sect1>
 840
 841<sect1 id="host-design-editbus"><title>The EditBus</title>
 842
 843<para>
 844  The
 845  EditBus maintains a list of objects that have requested to receive
 846  messages. When a message is sent using this class, all registered
 847  components receive it in turn.
 848</para>
 849
 850<para>
 851  Plugins register with the EditBus to receive messages reflecting
 852  changes in the application's state, including changes in buffers,
 853  views and editing panes, changes in the set of properties maintained
 854  by the application, and the closing of the application.  A full list
 855  of message classes used by the EditBus are summarized beginning with
 856  <xref linkend="class-ebmessage"/>.
 857</para>
 858
 859<para>
 860<indexterm>
 861  <primary>Plugin API</primary>
 862  <secondary>EBComponent class</secondary>
 863</indexterm>
 864  Classes for objects that subscribe to the EditBus must implement the
 865  <classname>EBComponent</classname> interface, which defines the single
 866  method <function>handleMessage()</function>. A
 867  <classname>View</classname>, for example, can receive and handle EditBus
 868  messages because it also implements <classname>EBComponent</classname>.
 869</para>
 870
 871<para>
 872  Any class in a plugin can receive messages by implementing
 873  the <classname>EBComponent</classname>
 874  interface.  A <quote>plugin core class</quote> that extends the
 875  <classname>EBPlugin</classname> abstract class (and whose name ends with
 876  <quote>Plugin</quote> for identification purposes) will automatically be
 877  added to the EditBus during jEdit's startup routine.  Any other
 878  class - for example, a docking window component that needs to receive
 879  notification of buffer changes - must perform its own registration by calling
 880  <function>EditBus.addToBus(this)</function> during its initialization.
 881  If this class if derived from <classname>JComponent</classname>, a
 882  convenient place to register would be in an implementation of the
 883  <classname>JComponent</classname> method
 884  <function>addNotify()</function>.
 885</para>
 886
 887<sect2 id="class-ebcomponent"><title>Interface EBComponent</title>
 888
 889<para>
 890  Every plugin class that uses the EditBus for receiving
 891  messages
 892  must implement this interface.
 893</para>
 894
 895<para>
 896  The <classname>EBComponent</classname> interface contains a single
 897  method that an implementing class (including any class derived from
 898  <classname>EBPlugin</classname>) must provide:
 899</para>
 900
 901<itemizedlist>
 902  <listitem>
 903    <funcsynopsis>
 904      <funcprototype>
 905        <funcdef>public void <function>handleMessage</function></funcdef>
 906        <paramdef>EBMessage <parameter>message</parameter></paramdef>
 907      </funcprototype>
 908    </funcsynopsis>
 909  </listitem>
 910</itemizedlist>
 911
 912<para>
 913  The parameter's type, <classname>EBMessage</classname>, is another
 914  abstract class which establishes the core elements of any message that
 915  is published to the EditBus. It has two attributes: an
 916  <classname>EBComponent</classname> that is the source of the message
 917  (the source will be <classname>null</classname> in some cases),
 918  and a <classname>boolean</classname> data member, <varname>vetoed</varname>. This
 919  flag indicates whether a prior recipient of the message has determined
 920  that the message has been handled and need not be passed on to other
 921  subscribers. The flag is set by a call
 922  to the <function>veto()</function> method of the
 923  <classname>EBMessage</classname>. Some message classes, however,
 924  are configured so that they cannot be vetoed, to ensure they are
 925  received by all subscribers.
 926</para>
 927
 928<para>
 929  Message classes extending <classname>EBMessage</classname> typically add
 930  other data members and methods to provide subscribers with whatever is
 931  needed to handle the message appropriately. Descriptions of specific
 932  message classes can be found in <xref linkend="api-message"/>.
 933</para>
 934
 935<para>
 936  The <function>handleMessage()</function> method
 937  must specify the type of responses
 938  the plugin will have for various subclasses of the
 939  <classname>EBMessage</classname> class. Typically this is done with
 940  one or more <function>if</function> blocks that test whether the message
 941  is an instance of a derived message class in which the plugin has an
 942  interest, as in the following example:
 943</para>
 944
 945<informalexample><programlisting>if(msg instanceof BufferUpdate) {
 946    // a buffer's state has changed!
 947}
 948else if(msg instanceof ViewUpdate) {
 949    // a view's state has changed!
 950}
 951// ... and so on</programlisting></informalexample>
 952
 953<para>
 954  Note that any object, whether or not derived from
 955  <classname>EBComponent</classname>, can send a message to the EditBus
 956  by calling the static method <function>EditBus.send()</function>.
 957  This method takes a single parameter, an <classname>EBMessage</classname>
 958  object that is the message being sent. Most plugins, however, will
 959  only concern themselves with receiving, not sending, messages.
 960</para>
 961
 962</sect2>
 963
 964</sect1>
 965
 966<sect1 id="host-design-conclusion"><title>Conclusion</title>
 967
 968<para>
 969  At this point, we can identify the following practical requirements
 970  for a plugin:
 971</para>
 972
 973<itemizedlist>
 974  <listitem><para>
 975    it must be packaged as one or more JAR archives and contain a class
 976    file ending with the prefix <filename>Plugin</filename> that extends
 977    the <classname>EditPlugin</classname> abstract class;
 978  </para></listitem>
 979  <listitem><para>
 980    the archive must contain
 981    at least one properties file having a <filename>.props</filename>
 982    extension. Certain properties giving information
 983    about the plugin must be defined.
 984  </para></listitem>
 985  <listitem><para>
 986    if the plugin will provide a visible interface, the JAR archive must contain
 987    an XML data file named <filename>dockables.xml</filename> containing
 988    BeanShell code for creating a container for that interface;
 989  </para></listitem>
 990  <listitem><para>
 991    the JAR archive may contain data concerning actions for display
 992    in jEdit's menu bar and elsewhere in a file entitled
 993    <filename>actions.xml</filename>; and
 994  </para></listitem>
 995  <listitem><para>
 996    if the plugin must respond as a whole to changes in the state of the jEdit
 997    application, the plugin core class should be derived from the
 998    <classname>EBPlugin</classname> class instead of directly from
 999    <classname>EditPlugin</classname>
1000  </para></listitem>
1001</itemizedlist>
1002
1003<para>
1004  We will provide more detail on these requirements later.
1005</para>
1006
1007</sect1>
1008
1009</chapter>