PageRenderTime 59ms CodeModel.GetById 43ms app.highlight 10ms RepoModel.GetById 0ms app.codeStats 1ms


HTML | 315 lines | 293 code | 22 blank | 0 comment | 0 complexity | cc6b70282496d8a16e1eb0b0a76f5373 MD5 | raw file
  1<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>Getting Input for a Macro</title><meta name="generator" content="DocBook XSL Stylesheets V1.65.1"><link rel="home" href="index.html" title="jEdit 4.2 User's Guide"><link rel="up" href="macro-tips.html" title="Chapter 15. Macro Tips and Techniques"><link rel="previous" href="macro-tips.html" title="Chapter 15. Macro Tips and Techniques"><link rel="next" href="startup-scripts.html" title="Startup Scripts"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Getting Input for a Macro</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="macro-tips.html">Prev</a> </td><th width="60%" align="center">Chapter 15. Macro Tips and Techniques</th><td width="20%" align="right"> <a accesskey="n" href="startup-scripts.html">Next</a></td></tr></table><hr></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="macro-tips-input"></a>Getting Input for a Macro</h2></div></div><div></div></div><p>
  2    The dialog-based macro discussed in <a href="dialog-macro.html" title="Chapter 14. A Dialog-Based Macro">Chapter 14, <i>A Dialog-Based Macro</i></a>
  3    reflects a conventional approach to obtaining input in a Java program.
  4    Nevertheless, it can be too lengthy or tedious for someone
  5    trying to write a macro quickly. Not every macro needs a user interface
  6    specified in such detail; some macros require only a single keystroke or
  7    no input at all. In this section we outline some other techniques for
  8    obtaining input that will help you write macros quickly.
  9  </p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="macro-tips-input-single-line"></a>Getting a Single Line of Text</h3></div></div><div></div></div><p>
 10    As mentioned earlier in <a href="helpful-methods.html" title="Helpful Methods in the
 11  Macros Class">the section called &#8220;Helpful Methods in the
 12  Macros Class&#8221;</a>, the method
 13    <tt class="function">Macros.input()</tt> offers a convenient way to obtain
 14    a single line of text input. Here is an example that inserts a pair
 15    of HTML markup tags specified by the user.
 16  </p><div class="informalexample"><table border="0" bgcolor="#E0E0E0"><tr><td><pre class="programlisting">// Insert_Tag.bsh
 18void insertTag()
 20    caret = textArea.getCaretPosition();
 21    tag = Macros.input(view, &#8220;<span class="quote">Enter name of tag:</span>&#8221;);
 22    if( tag == null || tag.length() == 0) return;
 23    text = textArea.getSelectedText();
 24    if(text == null) text = &#8220;<span class="quote"></span>&#8221;;
 25    sb = new StringBuffer();
 26    sb.append(&#8220;<span class="quote">&lt;</span>&#8221;).append(tag).append(&#8220;<span class="quote">&gt;</span>&#8221;);
 27    sb.append(text);
 28    sb.append(&#8220;<span class="quote">&lt;/</span>&#8221;).append(tag).append(&#8220;<span class="quote">&gt;</span>&#8221;);
 29    textArea.setSelectedText(sb.toString());
 30    if(text.length() == 0)
 31        textArea.setCaretPosition(caret + tag.length() + 2);
 36// end Insert_Tag.bsh</pre></td></tr></table></div><p>
 37    Here the call to <tt class="function">Macros.input()</tt> seeks the name
 38    of the markup tag. This method sets the message box title to a fixed string,
 39    &#8220;<span class="quote">Macro input</span>&#8221;, but the specific message <span><b class="guilabel">Enter name
 40    of tag</b></span> provides all the information necessary. The return value
 41    <tt class="varname">tag</tt> must be tested to see if it is null.  This would
 42    occur if the user presses the <span><b class="guilabel">Cancel</b></span> button or
 43    closes the dialog window displayed by <tt class="function">Macros.input()</tt>.
 44  </p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="macro-tips-input-multiple-data"></a>Getting Multiple Data Items</h3></div></div><div></div></div><p>
 45    If more than one item of input is needed, a succession of calls to
 46    <tt class="function">Macros.input()</tt> is a possible, but awkward approach,
 47    because it would not be possible to correct early input after the
 48    corresponding message box is dismissed.  Where more is required,
 49    but a full dialog layout is either unnecessary or too much work,
 50    the Java method <tt class="function">JOptionPane.showConfirmDialog()</tt>
 51    is available. The version to use has the following prototype:
 52  </p><div class="itemizedlist"><ul type="disc"><li><div class="funcsynopsis"><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0"><tr><td><code class="funcdef">public static int <b class="fsfunc">showConfirmDialog</b>(</code></td><td>Component  </td><td><var class="pdparam">parentComponent</var>, </td></tr><tr><td> </td><td>Object  </td><td><var class="pdparam">message</var>, </td></tr><tr><td> </td><td>String  </td><td><var class="pdparam">title</var>, </td></tr><tr><td> </td><td>int  </td><td><var class="pdparam">optionType</var>, </td></tr><tr><td> </td><td>int  </td><td><var class="pdparam">messageType</var><code>)</code>;</td></tr></table></div></li></ul></div><p>
 53    The usefulness of this method arises from the fact that the
 54    <tt class="varname">message</tt> parameter can be an object of any
 55    Java class (since all classes are derived from
 56    <tt class="classname">Object</tt>), or any array of objects.  The
 57    following example shows how this feature can be used.
 58  </p><div class="informalexample"><table border="0" bgcolor="#E0E0E0"><tr><td><pre class="programlisting">// excerpt from Write_File_Header.bsh
 60title = &#8220;<span class="quote">Write file header</span>&#8221;;
 62currentName = buffer.getName();
 64nameField = new JTextField(currentName);
 65authorField = new JTextField(&#8220;<span class="quote">Your name here</span>&#8221;);
 66descField = new JTextField(&#8220;<span class="quote"></span>&#8221;, 25);
 68namePanel = new JPanel(new GridLayout(1, 2));
 69nameLabel = new JLabel(&#8220;<span class="quote">Name of file:</span>&#8221;, SwingConstants.LEFT);
 70saveField = new JCheckBox(&#8220;<span class="quote">Save file when done</span>&#8221;,
 71    !buffer.isNewFile());
 76message = new Object[9];
 77message[0] = namePanel;
 78message[1] = nameField;
 79message[2] = Box.createVerticalStrut(10);
 80message[3] = &#8220;<span class="quote">Author's name:</span>&#8221;;
 81message[4] = authorField;
 82message[5] = Box.createVerticalStrut(10);
 83message[6] = &#8220;<span class="quote">Enter description:</span>&#8221;;
 84message[7] = descField;
 85message[8] = Box.createVerticalStrut(5);
 87if( JOptionPane.OK_OPTION !=
 88    JOptionPane.showConfirmDialog(view, message, title,
 89        JOptionPane.OK_CANCEL_OPTION,
 90        JOptionPane.QUESTION_MESSAGE))
 91    return null;
 93// *****remainder of macro script omitted*****
 95// end excerpt from Write_File_Header.bsh</pre></td></tr></table></div><p>
 96    This macro takes several items of user input and produces a formatted
 97    file header at the beginning of the buffer. The full macro is included in
 98    the set of macros installed by jEdit. There are a number of input
 99    features of this excerpt worth noting.
100  </p><div class="itemizedlist"><ul type="disc"><li><p>
101        The macro uses a total of seven visible components. Two of them are
102        created behind the scenes by <tt class="function">showConfirmDialog()</tt>,
103        the rest are made by the macro. To arrange them, the script creates an
104        array of <tt class="classname">Object</tt> objects and assigns components to
105        each location in the array. This translates to a fixed, top-to-bottom
106        arrangement in the message box created by
107        <tt class="function">showConfirmDialog()</tt>.
108      </p></li><li><p>
109        The macro uses <tt class="classname">JTextField</tt> objects to
110        obtain most of the input data.  The fields <tt class="varname">nameField</tt>
111        and <tt class="varname">authorField</tt> are created with constructors
112        that take the initial, default text to be displayed in the field as a
113        parameter.  When the message box is displayed, the default text
114        will appear and can be altered or deleted by the user.
115      </p></li><li><p>
116        The text field <tt class="varname">descField</tt> uses an empty string for its
117        initial value. The second parameter in its constructor sets the width of
118        the text field component, expressed as the number of characters of
119        &#8220;<span class="quote">average</span>&#8221; width. When
120        <tt class="function">showConfirmDialog()</tt> prepares the layout of the
121        message box, it sets the width wide enough to accommodate the
122        designated with of <tt class="varname">descField</tt>. This technique produces
123        a message box and input text fields that are wide enough for your data
124        with one line of code.
125      </p></li><li><p>
126        The displayed message box includes a <tt class="classname">JCheckBox</tt>
127        component that determines whether the buffer will be saved to disk
128        immediately after the file header is written. To conserve space
129        in the message box, we want to display the check box to the
130        right of the label <span><b class="guilabel">Name of file:</b></span>. To do that,
131        we create a <tt class="classname">JPanel</tt> object and populate it with
132        the label and the checkbox in a left-to-right
133        <tt class="classname">GridLayout</tt>.  The <tt class="classname">JPanel</tt>
134        containing the two components is then added to the beginning of
135        <tt class="varname">message</tt> array.
136      </p></li><li><p>
137        The two visible components created by
138        <tt class="function">showConfirmDialog()</tt> appear at positions 3 and 6 of
139        the <tt class="varname">message</tt> array. Only the text is required; they
140        are rendered as text labels.
141      </p></li><li><p>
142        There are three invisible components created by
143        <tt class="function">showConfirmDialog()</tt>.  Each of them involves
144        a call to <tt class="function">Box.createVerticalStrut()</tt>.  The
145        <tt class="classname">Box</tt> class is a sophisticated layout class
146        that gives the user great flexibility in sizing and positioning
147        components. Here we use a <tt class="function">static</tt> method of
148        the <tt class="classname">Box</tt> class that produces a vertical
149        <i class="glossterm">strut</i>.  This is a transparent component
150        whose width expands to fill its parent component (in this case,
151        the message box).  The single parameter indicates the height
152        of the strut in pixels.  The last call to
153        <tt class="function">createVerticalStrut()</tt> separates the
154        description text field from the <span><b class="guilabel">OK</b></span> and
155        <span><b class="guilabel">Cancel</b></span> buttons that are automatically added
156        by <tt class="function">showConfirmDialog()</tt>.
157      </p></li><li><p>
158        Finally, the call to <tt class="function">showConfirmDialog()</tt> uses
159        defined constants for the option type and the message type.  The
160        constants are the same as those used with the
161        <tt class="function">Macros.confirm()</tt> method; see
162        <a href="helpful-methods.html" title="Helpful Methods in the
163  Macros Class">the section called &#8220;Helpful Methods in the
164  Macros Class&#8221;</a>. The
165        option type signifies the use of <span><b class="guilabel">OK</b></span>
166        and <span><b class="guilabel">Cancel</b></span> buttons. The
167        <tt class="constant">QUERY_MESSAGE</tt> message type causes the message box
168        to display a question mark icon.
169      </p><p>
170        The return value of the method
171        is tested against the value <tt class="constant">OK_OPTION</tt>.  If
172        the return value is something else (because the
173        <span><b class="guilabel">Cancel</b></span> button was pressed or because the
174        message box window was closed without a button press), a
175        <tt class="constant">null</tt> value is returned to a calling function,
176        signaling that the user canceled macro execution.  If the return
177        value is <tt class="constant">OK_OPTION</tt>, each of the input components
178        can yield their contents for further processing by calls to
179        <tt class="function">JTextField.getText()</tt> (or, in the case of
180        the check box, <tt class="function">JCheckBox.isSelected()</tt>).
181      </p></li></ul></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="tips-macro-input-combo"></a>Selecting Input From a List</h3></div></div><div></div></div><p>
182  Another useful way to get user input for a macro is to use a combo box
183  containing a number of pre-set options. If this is the only input
184  required, one of the versions of <tt class="function">showInputDialog()</tt>
185  in the <tt class="classname">JOptionPane</tt> class provides a shortcut.
186  Here is its prototype:
187</p><div class="itemizedlist"><ul type="disc"><li><div class="funcsynopsis"><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0"><tr><td><code class="funcdef">public static Object <b class="fsfunc">showInputDialog</b>(</code></td><td>Component  </td><td><var class="pdparam">parentComponent</var>, </td></tr><tr><td> </td><td>Object  </td><td><var class="pdparam">message</var>, </td></tr><tr><td> </td><td>String  </td><td><var class="pdparam">title</var>, </td></tr><tr><td> </td><td>int  </td><td><var class="pdparam">messageType</var>, </td></tr><tr><td> </td><td>Icon  </td><td><var class="pdparam">icon</var>, </td></tr><tr><td> </td><td>Object[]  </td><td><var class="pdparam">selectionValues</var>, </td></tr><tr><td> </td><td>Object  </td><td><var class="pdparam">initialSelectionValue</var><code>)</code>;</td></tr></table></div></li></ul></div><p>
188    This method creates a message box containing a drop-down list of the
189    options specified in the method's parameters, along with
190    <span><b class="guilabel">OK</b></span> and <span><b class="guilabel">Cancel</b></span> buttons.
191    Compared to <tt class="function">showConfirmDialog()</tt>, this method lacks
192    an <tt class="varname">optionType</tt> parameter and has three additional
193    parameters: an <tt class="varname">icon</tt> to display in the dialog
194    (which can be set to <tt class="constant">null</tt>), an array of
195    <tt class="varname">selectionValues</tt> objects, and a reference to one
196    of the options as the <tt class="varname">initialSelectionValue</tt> to be
197    displayed. In addition, instead of returning an <tt class="classname">int</tt>
198    representing the user's action, <tt class="function">showInputDialog()</tt>
199    returns the <tt class="classname">Object</tt> corresponding to the user's
200    selection, or <tt class="constant">null</tt> if the selection is canceled.
201  </p><p>
202    The following macro fragment illustrates the use of this method.
203  </p><div class="informalexample"><table border="0" bgcolor="#E0E0E0"><tr><td><pre class="programlisting">// fragment illustrating use of showInputDialog()
204options = new Object[5];
205options[0] = "JLabel";
206options[1] = "JTextField";
207options[2] = "JCheckBox";
208options[3] = "HistoryTextField";
209options[4} = "-- other --";
211result = JOptionPane.showInputDialog(view,
212    "Choose component class",
213    "Select class for input component",
214    JOptionPane.QUESTION_MESSAGE,
215    null, options, options[0]);</pre></td></tr></table></div><p>
216    The return value <tt class="varname">result</tt> will contain either the
217    <tt class="classname">String</tt> object representing the selected text
218    item or <tt class="constant">null</tt> representing no selection.  Any
219    further use of this fragment would have to test the value of
220    <tt class="varname">result</tt> and likely exit from the macro if the value
221    equaled <tt class="constant">null</tt>.
222  </p><p>
223    A set of options can be similarly placed in a
224    <tt class="classname">JComboBox</tt> component created as part of a larger
225    dialog or <tt class="function">showMessageDialog()</tt> layout.  Here are some
226    code fragments showing this approach:
227  </p><div class="informalexample"><table border="0" bgcolor="#E0E0E0"><tr><td><pre class="programlisting">// fragments from Display_Abbreviations.bsh
228// import statements and other code omitted
230// from main routine, this method call returns an array
231// of Strings representing the names of abbreviation sets
233abbrevSets = getActiveSets();
237// from showAbbrevs() method
239combo = new JComboBox(abbrevSets);
240// set width to uniform size regardless of combobox contents
241Dimension dim = combo.getPreferredSize();
242dim.width = Math.max(dim.width, 120);
244combo.setSelectedItem(STARTING_SET); // defined as "global"
246// end fragments</pre></td></tr></table></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="macro-tips-single-char"></a>Using a Single Keypress as Input</h3></div></div><div></div></div><p>
247    Some macros may choose to emulate the style of character-based text
248    editors such as <span class="application">emacs</span> or
249    <span class="application">vi</span>. They will require only a single keypress
250    as input that would be handled by the macro but not displayed on the
251    screen. If the keypress corresponds to a character value, jEdit can pass
252    that value as a parameter to a BeanShell script.
253  </p><p>
254    The jEdit class <a href="../api/org/gjt/sp/jedit/gui/InputHandler.html" target="_top">InputHandler</a> is an abstract class
255    that that manages associations between keyboard input and editing
256    actions, along with the recording of macros. Keyboard input
257    in jEdit is normally managed by the derived class
258    <a href="../api/org/gjt/sp/jedit/gui/DefaultInputHandler.html" target="_top">DefaultInputHandler</a>. One of the methods in
259    the <a href="../api/org/gjt/sp/jedit/gui/InputHandler.html" target="_top">InputHandler</a> class handles input from a
260    single keypress:
261  </p><div class="itemizedlist"><ul type="disc"><li><div class="funcsynopsis"><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0"><tr><td><code class="funcdef">public void <b class="fsfunc">readNextChar</b>(</code></td><td>String  </td><td><var class="pdparam">prompt</var>, </td></tr><tr><td> </td><td>String  </td><td><var class="pdparam">code</var><code>)</code>;</td></tr></table></div></li></ul></div><p>
262    When this method is called, the contents of the <tt class="varname">prompt</tt>
263    parameter is shown in the view's status
264    bar. The method then waits for a key press, after which
265    the contents of the <tt class="varname">code</tt> parameter will be run as
266    a BeanShell script, with one important modification. Each time the
267    string <tt class="varname">__char__</tt> appears in the parameter script, it
268    will be substituted by the character pressed. The key press
269    is &#8220;<span class="quote">consumed</span>&#8221; by <tt class="function">readNextChar()</tt>.
270    It will not be displayed on the screen or otherwise processed by jEdit.
271  </p><p>
272    Using <tt class="function">readNextChar()</tt> requires a macro within the
273    macro, formatted as a single, potentially lengthy string literal. The
274    following macro illustrates this technique. It selects a line of text
275    from the current caret position to the first occurrence of the character
276    next typed by the user. If the character does not appear on the line, no
277    new selection occurs and the display remains unchanged.
278  </p><div class="informalexample"><table border="0" bgcolor="#E0E0E0"><tr><td><pre class="programlisting">// Next_Char.bsh
280script = new StringBuffer(512);
281script.append( "start = textArea.getCaretPosition();"         );
282script.append( "line = textArea.getCaretLine();"              );
283script.append( "end = textArea.getLineEndOffset(line) + 1;"   );
284script.append( "text = buffer.getText(start, end - start);"   );
285script.append( "match = text.indexOf(__char__, 1);"           );
286script.append( "if(match != -1) {"                            );
287script.append(   "if(__char__ != '\\n') ++match;"             );
288script.append(   ", start + match - 1);" );
289script.append( "}"                                            );
291view.getInputHandler().readNextChar("Enter a character",
292    script.toString());
294// end Next_Char.bsh</pre></td></tr></table></div><p>
295    Once again, here are a few comments on the macro's design.
296  </p><div class="itemizedlist"><ul type="disc"><li><p>
297        A <tt class="classname">StringBuffer</tt> object is used for efficiency; it
298        obviates multiple creation of fixed-length <tt class="classname">String</tt>
299        objects. The parameter to the constructor of <tt class="varname">script</tt>
300        specifies the initial size of the buffer that will receive the contents
301        of the child script.
302      </p></li><li><p>
303        Besides the quoting of the script code, the formatting of the macro is
304        entirely optional but (hopefully) makes it easier to read.
305      </p></li><li><p>
306        It is important that the child script be self-contained.  It does
307        not run in the same namespace as the &#8220;<span class="quote">parent</span>&#8221; macro
308        <tt class="filename">Next_Char.bsh</tt> and therefore does not share
309        variables, methods, or scripted objects defined in the parent
310        macro.
311      </p></li><li><p>
312        Finally, access to the <a href="../api/org/gjt/sp/jedit/gui/InputHandler.html" target="_top">InputHandler</a> object used
313        by jEdit is available by calling
314        <tt class="function">getInputHandler()</tt> on the current view.
315      </p></li></ul></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="macro-tips.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="macro-tips.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="startup-scripts.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 15. Macro Tips and Techniques </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Startup Scripts</td></tr></table></div></body></html>