/www/tags/NOV_07_2009/htdocs/users-guide/macro-tips-input.html
HTML | 294 lines | 272 code | 22 blank | 0 comment | 0 complexity | 8ebf5063dcc3e53663d7e2c25d86fd81 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
- <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.73.2"><link rel="start" href="index.html" title="jEdit 4.3 User's Guide"><link rel="up" href="macro-tips.html" title="Chapter 15. Macro Tips and Techniques"><link rel="prev" 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><p>The dialog-based macro discussed in <a class="xref" href="dialog-macro.html" title="Chapter 14. A Dialog-Based Macro">Chapter 14, <i>A Dialog-Based Macro</i></a> reflects a conventional approach to obtaining
- input in a Java program. Nevertheless, it can be too lengthy or tedious
- for someone trying to write a macro quickly. Not every macro needs a
- user interface specified in such detail; some macros require only a
- single keystroke or no input at all. In this section we outline some
- other techniques for obtaining input that will help you write macros
- quickly.</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><p>As mentioned earlier in <a class="xref" href="helpful-methods.html" title="Helpful Methods in the Macros Class">the section called “Helpful Methods in the Macros Class”</a>,
- the method <code class="function">Macros.input()</code> offers a convenient
- way to obtain a single line of text input. Here is an example that
- inserts a pair of HTML markup tags specified by the user.</p><div class="informalexample"><pre class="programlisting">// Insert_Tag.bsh
- void insertTag()
- {
- caret = textArea.getCaretPosition();
- tag = Macros.input(view, “<span class="quote">Enter name of tag:</span>”);
- if( tag == null || tag.length() == 0) return;
- text = textArea.getSelectedText();
- if(text == null) text = “<span class="quote"></span>”;
- sb = new StringBuffer();
- sb.append(“<span class="quote"><</span>”).append(tag).append(“<span class="quote">></span>”);
- sb.append(text);
- sb.append(“<span class="quote"></</span>”).append(tag).append(“<span class="quote">></span>”);
- textArea.setSelectedText(sb.toString());
- if(text.length() == 0)
- textArea.setCaretPosition(caret + tag.length() + 2);
- }
- insertTag();
- // end Insert_Tag.bsh</pre></div><p>Here the call to <code class="function">Macros.input()</code> seeks the
- name of the markup tag. This method sets the message box title to a
- fixed string, “<span class="quote">Macro input</span>”, but the specific message
- <span class="guilabel"><strong>Enter name of tag</strong></span> provides all the information
- necessary. The return value <code class="varname">tag</code> must be tested to
- see if it is null. This would occur if the user presses the
- <span class="guilabel"><strong>Cancel</strong></span> button or closes the dialog window
- displayed by <code class="function">Macros.input()</code>.</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><p>If more than one item of input is needed, a succession of
- calls to <code class="function">Macros.input()</code> is a possible, but
- awkward approach, because it would not be possible to correct early
- input after the corresponding message box is dismissed. Where more
- is required, but a full dialog layout is either unnecessary or too
- much work, the Java method
- <code class="function">JOptionPane.showConfirmDialog()</code> is available.
- The version to use has the following prototype:</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>The usefulness of this method arises from the fact that the
- <code class="varname">message</code> parameter can be an object of any Java
- class (since all classes are derived from
- <code class="classname">Object</code>), or any array of objects. The
- following example shows how this feature can be used.</p><div class="informalexample"><pre class="programlisting">// excerpt from Write_File_Header.bsh
- title = “<span class="quote">Write file header</span>”;
- currentName = buffer.getName();
- nameField = new JTextField(currentName);
- authorField = new JTextField(“<span class="quote">Your name here</span>”);
- descField = new JTextField(“<span class="quote"></span>”, 25);
- namePanel = new JPanel(new GridLayout(1, 2));
- nameLabel = new JLabel(“<span class="quote">Name of file:</span>”, SwingConstants.LEFT);
- saveField = new JCheckBox(“<span class="quote">Save file when done</span>”,
- !buffer.isNewFile());
- namePanel.add(nameLabel);
- namePanel.add(saveField);
- message = new Object[9];
- message[0] = namePanel;
- message[1] = nameField;
- message[2] = Box.createVerticalStrut(10);
- message[3] = “<span class="quote">Author's name:</span>”;
- message[4] = authorField;
- message[5] = Box.createVerticalStrut(10);
- message[6] = “<span class="quote">Enter description:</span>”;
- message[7] = descField;
- message[8] = Box.createVerticalStrut(5);
- if( JOptionPane.OK_OPTION !=
- JOptionPane.showConfirmDialog(view, message, title,
- JOptionPane.OK_CANCEL_OPTION,
- JOptionPane.QUESTION_MESSAGE))
- return null;
- // *****remainder of macro script omitted*****
- // end excerpt from Write_File_Header.bsh</pre></div><p>This macro takes several items of user input and produces a
- formatted file header at the beginning of the buffer. The full macro
- is included in the set of macros installed by jEdit. There are a
- number of input features of this excerpt worth noting.</p><div class="itemizedlist"><ul type="disc"><li><p>The macro uses a total of seven visible components.
- Two of them are created behind the scenes by
- <code class="function">showConfirmDialog()</code>, the rest are made
- by the macro. To arrange them, the script creates an array
- of <code class="classname">Object</code> objects and assigns
- components to each location in the array. This translates to
- a fixed, top-to-bottom arrangement in the message box
- created by <code class="function">showConfirmDialog()</code>.</p></li><li><p>The macro uses <code class="classname">JTextField</code>
- objects to obtain most of the input data. The fields
- <code class="varname">nameField</code> and
- <code class="varname">authorField</code> are created with constructors
- that take the initial, default text to be displayed in the
- field as a parameter. When the message box is displayed, the
- default text will appear and can be altered or deleted by
- the user.</p></li><li><p>The text field <code class="varname">descField</code> uses an
- empty string for its initial value. The second parameter in
- its constructor sets the width of the text field component,
- expressed as the number of characters of
- “<span class="quote">average</span>” width. When
- <code class="function">showConfirmDialog()</code> prepares the layout
- of the message box, it sets the width wide enough to
- accommodate the designated with of
- <code class="varname">descField</code>. This technique produces a
- message box and input text fields that are wide enough for
- your data with one line of code.</p></li><li><p>The displayed message box includes a
- <code class="classname">JCheckBox</code> component that determines
- whether the buffer will be saved to disk immediately after
- the file header is written. To conserve space in the message
- box, we want to display the check box to the right of the
- label <span class="guilabel"><strong>Name of file:</strong></span>. To do that, we
- create a <code class="classname">JPanel</code> object and populate
- it with the label and the checkbox in a left-to-right
- <code class="classname">GridLayout</code>. The
- <code class="classname">JPanel</code> containing the two components
- is then added to the beginning of <code class="varname">message</code>
- array.</p></li><li><p>The two visible components created by
- <code class="function">showConfirmDialog()</code> appear at positions
- 3 and 6 of the <code class="varname">message</code> array. Only the
- text is required; they are rendered as text labels.</p></li><li><p>There are three invisible components created by
- <code class="function">showConfirmDialog()</code>. Each of them
- involves a call to
- <code class="function">Box.createVerticalStrut()</code>. The
- <code class="classname">Box</code> class is a sophisticated layout
- class that gives the user great flexibility in sizing and
- positioning components. Here we use a
- <code class="function">static</code> method of the
- <code class="classname">Box</code> class that produces a vertical
- <em class="glossterm">strut</em>. This is a transparent
- component whose width expands to fill its parent component
- (in this case, the message box). The single parameter
- indicates the height of the strut in pixels. The last call
- to <code class="function">createVerticalStrut()</code> separates the
- description text field from the <span class="guilabel"><strong>OK</strong></span> and
- <span class="guilabel"><strong>Cancel</strong></span> buttons that are automatically
- added by <code class="function">showConfirmDialog()</code>.</p></li><li><p>Finally, the call to
- <code class="function">showConfirmDialog()</code> uses defined
- constants for the option type and the message type. The
- constants are the same as those used with the
- <code class="function">Macros.confirm()</code> method; see <a class="xref" href="helpful-methods.html" title="Helpful Methods in the Macros Class">the section called “Helpful Methods in the Macros Class”</a>. The option type signifies the
- use of <span class="guilabel"><strong>OK</strong></span> and
- <span class="guilabel"><strong>Cancel</strong></span> buttons. The
- <code class="constant">QUERY_MESSAGE</code> message type causes the
- message box to display a question mark icon.</p><p>The return value of the method is tested against the
- value <code class="constant">OK_OPTION</code>. If the return value is
- something else (because the <span class="guilabel"><strong>Cancel</strong></span>
- button was pressed or because the message box window was
- closed without a button press), a <code class="constant">null</code>
- value is returned to a calling function, signaling that the
- user canceled macro execution. If the return value is
- <code class="constant">OK_OPTION</code>, each of the input components
- can yield their contents for further processing by calls to
- <code class="function">JTextField.getText()</code> (or, in the case
- of the check box,
- <code class="function">JCheckBox.isSelected()</code>).</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><p>Another useful way to get user input for a macro is to use a
- combo box containing a number of pre-set options. If this is the
- only input required, one of the versions of
- <code class="function">showInputDialog()</code> in the
- <code class="classname">JOptionPane</code> class provides a shortcut. Here
- is its prototype:</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>This method creates a message box containing a drop-down list
- of the options specified in the method's parameters, along with
- <span class="guilabel"><strong>OK</strong></span> and <span class="guilabel"><strong>Cancel</strong></span> buttons.
- Compared to <code class="function">showConfirmDialog()</code>, this method
- lacks an <code class="varname">optionType</code> parameter and has three
- additional parameters: an <code class="varname">icon</code> to display in the
- dialog (which can be set to <code class="constant">null</code>), an array of
- <code class="varname">selectionValues</code> objects, and a reference to one
- of the options as the <code class="varname">initialSelectionValue</code> to be
- displayed. In addition, instead of returning an
- <code class="classname">int</code> representing the user's action,
- <code class="function">showInputDialog()</code> returns the
- <code class="classname">Object</code> corresponding to the user's selection,
- or <code class="constant">null</code> if the selection is canceled.</p><p>The following macro fragment illustrates the use of this
- method.</p><div class="informalexample"><pre class="programlisting">// fragment illustrating use of showInputDialog()
- options = new Object[5];
- options[0] = "JLabel";
- options[1] = "JTextField";
- options[2] = "JCheckBox";
- options[3] = "HistoryTextField";
- options[4} = "-- other --";
- result = JOptionPane.showInputDialog(view,
- "Choose component class",
- "Select class for input component",
- JOptionPane.QUESTION_MESSAGE,
- null, options, options[0]);</pre></div><p>The return value <code class="varname">result</code> will contain either
- the <code class="classname">String</code> object representing the selected
- text item or <code class="constant">null</code> representing no selection.
- Any further use of this fragment would have to test the value of
- <code class="varname">result</code> and likely exit from the macro if the
- value equaled <code class="constant">null</code>.</p><p>A set of options can be similarly placed in a
- <code class="classname">JComboBox</code> component created as part of a
- larger dialog or <code class="function">showMessageDialog()</code> layout.
- Here are some code fragments showing this approach:</p><div class="informalexample"><pre class="programlisting">// fragments from Display_Abbreviations.bsh
- // import statements and other code omitted
- // from main routine, this method call returns an array
- // of Strings representing the names of abbreviation sets
- abbrevSets = getActiveSets();
- ...
- // from showAbbrevs() method
- combo = new JComboBox(abbrevSets);
- // set width to uniform size regardless of combobox contents
- Dimension dim = combo.getPreferredSize();
- dim.width = Math.max(dim.width, 120);
- combo.setPreferredSize(dim);
- combo.setSelectedItem(STARTING_SET); // defined as "global"
- // end fragments</pre></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><p>Some macros may choose to emulate the style of character-based
- text editors such as <span class="application">emacs</span> or
- <span class="application">vi</span>. They will require only a single
- keypress as input that would be handled by the macro but not
- displayed on the screen. If the keypress corresponds to a character
- value, jEdit can pass that value as a parameter to a BeanShell
- script.</p><p>The jEdit class <a class="ulink" href="../api/org/gjt/sp/jedit/gui/InputHandler.html" target="_top">InputHandler</a>
- is an abstract class that that manages associations between keyboard
- input and editing actions, along with the recording of macros.
- Keyboard input in jEdit is normally managed by the derived class
- <a class="ulink" href="../api/org/gjt/sp/jedit/gui/DefaultInputHandler.html" target="_top">DefaultInputHandler</a>.
- One of the methods in the <a class="ulink" href="../api/org/gjt/sp/jedit/gui/InputHandler.html" target="_top">InputHandler</a>
- class handles input from a single keypress:</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>When this method is called, the contents of the
- <code class="varname">prompt</code> parameter is shown in the view's status
- bar. The method then waits for a key press, after which the contents
- of the <code class="varname">code</code> parameter will be run as a BeanShell
- script, with one important modification. Each time the string
- <code class="varname">__char__</code> appears in the parameter script, it will
- be substituted by the character pressed. The key press is
- “<span class="quote">consumed</span>” by <code class="function">readNextChar()</code>. It
- will not be displayed on the screen or otherwise processed by
- jEdit.</p><p>Using <code class="function">readNextChar()</code> requires a macro
- within the macro, formatted as a single, potentially lengthy string
- literal. The following macro illustrates this technique. It selects
- a line of text from the current caret position to the first
- occurrence of the character next typed by the user. If the character
- does not appear on the line, no new selection occurs and the display
- remains unchanged.</p><div class="informalexample"><pre class="programlisting">// Next_Char.bsh
- script = new StringBuffer(512);
- script.append( "start = textArea.getCaretPosition();" );
- script.append( "line = textArea.getCaretLine();" );
- script.append( "end = textArea.getLineEndOffset(line) + 1;" );
- script.append( "text = buffer.getText(start, end - start);" );
- script.append( "match = text.indexOf(__char__, 1);" );
- script.append( "if(match != -1) {" );
- script.append( "if(__char__ != '\\n') ++match;" );
- script.append( "textArea.select(start, start + match - 1);" );
- script.append( "}" );
- view.getInputHandler().readNextChar("Enter a character",
- script.toString());
- // end Next_Char.bsh</pre></div><p>Once again, here are a few comments on the macro's
- design.</p><div class="itemizedlist"><ul type="disc"><li><p>A <code class="classname">StringBuffer</code> object is used
- for efficiency; it obviates multiple creation of
- fixed-length <code class="classname">String</code> objects. The
- parameter to the constructor of <code class="varname">script</code>
- specifies the initial size of the buffer that will receive
- the contents of the child script.</p></li><li><p>Besides the quoting of the script code, the formatting
- of the macro is entirely optional but (hopefully) makes it
- easier to read.</p></li><li><p>It is important that the child script be
- self-contained. It does not run in the same namespace as the
- “<span class="quote">parent</span>” macro
- <code class="filename">Next_Char.bsh</code> and therefore does not
- share variables, methods, or scripted objects defined in the
- parent macro.</p></li><li><p>Finally, access to the <a class="ulink" href="../api/org/gjt/sp/jedit/gui/InputHandler.html" target="_top">InputHandler</a>
- object used by jEdit is available by calling
- <code class="function">getInputHandler()</code> on the current
- view.</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>